Esempio n. 1
0
 /**
  * Выполнение запроса
  * @param nc_search_query $query
  * @param boolean $should_highlight
  * @return nc_search_result
  */
 public function find(nc_search_query $query, $should_highlight = true)
 {
     $db = $this->get_db();
     $id_list = "0";
     $translator = new nc_search_provider_index_translator($this);
     // get IDs
     $select_ids_query = $query->translate($translator);
     $limit = (int) $query->get('limit');
     $offset = (int) $query->get('offset');
     $total_hits_unknown = false;
     if ($select_ids_query) {
         // neither null nor empty string
         $db->last_error = null;
         if (is_array($select_ids_query)) {
             // will need to create a temporary table; no final row count
             $prefilter_query = $select_ids_query["prefilter"];
             $refinement_query = $select_ids_query["refinement"];
             $query_hash = sha1($prefilter_query);
             // (1) create temporary table
             $db->query("SET @rank=0");
             $db->query("CREATE TEMPORARY TABLE `{$select_ids_query['temp_table']}` " . "(INDEX (`Rank`,`Document_ID`)) " . "SELECT filtered.`Document_ID`, @rank := @rank+1 AS `Rank` " . "FROM ({$prefilter_query}) AS filtered");
             // (2) check for cached offset values so we won't need to check from the beginning of the pre-filtered list
             $rank_table = $this->last_rank_table_name;
             $db->query("DELETE FROM `{$rank_table}` WHERE `Time` < NOW() - INTERVAL {$this->rank_cache_interval}");
             $cached_rank = $offset ? $db->get_row("SELECT `Offset`, `Rank` FROM `{$rank_table}`\n" . "WHERE `QueryHash` = '{$query_hash}' AND `Offset` <= {$offset}\n" . "ORDER BY `Offset` DESC\nLIMIT 1", ARRAY_A) : null;
             if ($cached_rank) {
                 $refinement_offset = $offset - $cached_rank["Offset"];
                 $refinement_rank_value = $cached_rank["Rank"];
             } else {
                 $refinement_offset = $offset;
                 $refinement_rank_value = 0;
             }
             $db->query("SET @rank_value = {$refinement_rank_value}");
             // (3) select IDs
             $db->query("{$refinement_query}\n" . "LIMIT " . ($limit + 1) . " OFFSET {$refinement_offset}");
             $ids = $db->get_col();
             $id_list = join(', ', $ids);
             if (count($ids) > $limit) {
                 // has next page
                 // total result count is set to (current page + 1 page)
                 // so there will be a paginator
                 $total_hits = $offset + 2 * $limit;
                 $total_hits_unknown = true;
                 // save rank for the next page
                 $last_rank = $db->get_var(null, 1, $limit);
                 $db->query("REPLACE INTO `{$this->last_rank_table_name}`\n                                    SET `Time` = NOW(),\n                                        `QueryHash` = '{$query_hash}',\n                                        `Offset` = " . ($offset + $limit) . ",\n                                        `Rank` = {$last_rank}");
             } else {
                 $total_hits = $offset + count($ids);
             }
         } else {
             // select IDs in a single query
             $id_list = join(', ', $db->get_col($select_ids_query));
             $total_hits = $db->last_error ? 0 : $db->get_var("SELECT FOUND_ROWS()");
         }
     } else {
         // Translator thinks there won't be any results (terms in the query are not in the index)
         // we could get $translator->get_unknown_terms(), but it is of no use for the correctors... :(
         $total_hits = 0;
     }
     // make 'result' object
     $result = new nc_search_result(array(), $total_hits);
     $result->set_query($query);
     /* @todo use $total_hits_unknown to mark that total count is not known */
     if (!$should_highlight) {
         $result->disable_highlighting();
     }
     if ($total_hits && $id_list) {
         // get field list
         $doc = new nc_search_result_document();
         $fields = $doc->get_column_names($query->get('options_to_fetch'));
         // get document data
         $doc_query = "SELECT {$fields} FROM `%t%` WHERE `Document_ID` IN ({$id_list}) " . "ORDER BY FIELD(`Document_ID`, {$id_list}) " . "LIMIT {$limit}";
         $result->select_from_database($doc_query);
     }
     return $result;
 }
Esempio n. 2
0
File: ui.php Progetto: Blu2z/implsk
 /**
  *
  * @param string $query_string
  * @param string|array $area
  * @param string $params Параметры, через амперсанд
  *   - field - поле поиска. Допустимые значения: 'title'
  *   - interval - непустое значение, если включена фильтрация по дате
  *   - intervalvalue - значение интервала
  *   - intervalunit - тип интервала (hour, day, week, month)
  *   - sortby - сортировка. Если пустое значение - сортировка по релевантности.
  *     Допустимые значения: last_updated или имя поля, по которому разрешена сортировка
  *   - sortdirection - desc (по умолчанию), asc
  *   - language - язык результатов, по умолчанию определяется автоматически
  *   - curPos - текущая позиция (номер первого результата)
  *   - recNum - количество результатов на странице, по умолчанию 10 (берется из
  *     настроек компонента в разделе)
  *   - correct - пытаться исправить запросы, не давшие результатов (по умолчанию
  *     равно соответствующей настройки модуля)
  *   - nologging - не записывать запрос в журнал запросов (при просмотре
  *     результатов из админки, чтобы не искажать картину запросов)
  * @return nc_search_data_persistent_collection
  */
 public function get_results($query_string, $area = "", $params = "")
 {
     if (!nc_search::should('EnableSearch')) {
         return new nc_search_result();
     }
     // return empty collection
     $start_time = microtime(true);
     $query_string = (string) $query_string;
     global $nc_core;
     parse_str($params, $params);
     if (isset($params["field"]) && $params["field"] && nc_search::should('AllowFieldSearch')) {
         $query_string = "{$params['field']}:({$query_string})";
     }
     $query = new nc_search_query($query_string);
     $has_interval = isset($params["interval"]) && isset($params["intervalvalue"]) && isset($params["intervalunit"]) && $params["interval"] && $params["intervalvalue"] && $params["intervalunit"];
     if ($has_interval) {
         $timestamp = strtotime("-{$params['intervalvalue']} {$params['intervalunit']}");
         $query->set('modified_after', strftime("%Y%m%d%H%M%S", $timestamp));
     }
     $allow_sort = isset($params["sortby"]) && $params["sortby"] && nc_search::should('AllowFieldSearch');
     if ($allow_sort) {
         $query->set('sort_by', $params["sortby"]);
         if (isset($params["sortdirection"]) && strtoupper($params["sortdirection"]) == 'ASC') {
             $query->set('sort_direction', SORT_ASC);
         }
     }
     if (isset($params["curPos"]) && $params["curPos"]) {
         $query->set('offset', (int) $params["curPos"]);
     }
     if (isset($params["recNum"]) && $params["recNum"]) {
         $query->set('limit', (int) $params["recNum"]);
     }
     if ($area) {
         if (is_array($area)) {
             $area = join(" ", $area);
         }
         $query->set('area', $area);
     }
     $language = isset($params["language"]) && $params["language"] ? $params["language"] : $nc_core->lang->detect_lang(1);
     $query->set('language', $language);
     $shutdown_page_path = nc_folder_path($nc_core->subdivision->get_current('Subdivision_ID'));
     register_shutdown_function('nc_search_shutdown', $shutdown_page_path, $query_string);
     $query_error = false;
     try {
         $results = nc_search::find($query);
     } catch (Exception $e) {
         $query_error = true;
         $results = new nc_search_result();
         $results->set_query($query)->set_error_message($e->getMessage());
     }
     $results->set_output_encoding(nc_core('NC_CHARSET'));
     // попробуем исправить, если не было результатов?
     $try_to_correct = $results->get_total_count() == 0 && !$query_error && (isset($params["correct"]) && $params["correct"] || nc_search::should('TryToCorrectQueries')) && preg_match_all('/[\\pL\\pN\\?\\*]+/u', $query_string, $tmp) <= nc_search::get_setting('MaxQueryLengthForCorrection');
     if ($try_to_correct) {
         $context = new nc_search_context(array("language" => $language, "action" => "searching"));
         $correctors = nc_search_extension_manager::get('nc_search_language_corrector', $context)->get_all();
         if (sizeof($correctors)) {
             $phrase = new nc_search_language_corrector_phrase($query_string);
             $rewritten_query = clone $query;
             foreach ($correctors as $corrector) {
                 if ($corrector->correct($phrase)) {
                     // что-то подправили
                     // попробуем поискать!
                     $rewritten_query->set('query_string', $phrase->to_string());
                     try {
                         $corrected_results = nc_search::find($rewritten_query);
                         if (sizeof($corrected_results)) {
                             $results = $corrected_results;
                             $results->set_correction_suggestion($phrase->get_suggestion());
                             $results->set_output_encoding(nc_core('NC_CHARSET'));
                             break;
                             // exit "foreach corrector"
                         }
                     } catch (Exception $e) {
                         // может упасть, например, если у изменённого слова есть несколько базовых форм...
                     }
                 }
                 // of "something changed"
             }
             // of "foreach corrector"
         }
         // end of "has correctors"
     }
     // end of "if ($try_to_correct)"
     $will_log = true;
     if (isset($params['nologging']) && $params['nologging'] && strlen($query_string)) {
         // только очень крутым чувакам разрешается не оставлять следов
         if (isset($GLOBALS['AUTH_USER_ID']) && isset($GLOBALS['perm']) && $GLOBALS["perm"]->isAccess(NC_PERM_MODULE)) {
             $will_log = false;
         }
     }
     if ($will_log && nc_search::should('SaveQueryHistory') && $query->get('offset') == 0) {
         $ip = ip2long($_SERVER['REMOTE_ADDR']);
         // achtung! не будет работать с IPv6!
         if ($ip > 0x7fffffff) {
             $ip -= 0x100000000;
         }
         // produce a signed 4-byte integer on 64-bit systems
         $query->set('results_count', $results->get_total_count())->set('user_ip', $ip)->set('user_id', $GLOBALS['AUTH_USER_ID'])->set('site_id', $GLOBALS['catalogue'])->save();
     }
     $results->set_search_time(microtime(true) - $start_time);
     return $results;
 }
Esempio n. 3
0
 /**
  * Поиск по индексу
  * @param nc_search_query $query
  * @param boolean $should_highlight
  * @return nc_search_result
  */
 public function find(nc_search_query $query, $should_highlight = true)
 {
     nc_search::set_current_context(new nc_search_context(array('search_provider' => get_class($this), 'action' => 'searching', 'language' => $query->get('language'))));
     $index = $this->get_index();
     $lucene_query = $this->get_lucene_query($query);
     if ($query->get('sort_by')) {
         // custom sort
         $lucene_result = $index->find($lucene_query, $query->get('sort_by'), SORT_STRING, $query->get('sort_direction'));
     } else {
         $lucene_result = $index->find($lucene_query);
     }
     $total_hits = count($lucene_result);
     $result = new nc_search_result(array(), $total_hits);
     $result->set_query($query);
     if (!$should_highlight) {
         $result->disable_highlighting();
     }
     nc_search::set_current_context();
     // truncate to get the requested page only
     $lucene_result = array_slice($lucene_result, $query->get('offset'), $query->get('limit'));
     // сформировать nc_search_result
     $result_ids = array();
     foreach ($lucene_result as $hit) {
         $result_ids[] = $hit->doc_id;
     }
     if (count($result_ids)) {
         foreach ($result_ids as $i => $id) {
             $result_ids[$i] = (int) trim($id, "x");
         }
         $id_list = join(", ", $result_ids);
         $doc = new nc_search_result_document();
         $fields = $doc->get_column_names($query->get('options_to_fetch'));
         $query = "SELECT {$fields} FROM `%t%` WHERE `Document_ID` IN ({$id_list}) " . "ORDER BY FIELD(`Document_ID`, {$id_list})";
         $result->select_from_database($query);
     }
     return $result;
 }