Пример #1
0
 /**
  * Установить свойство 'context' документа (фрагменты совпавшего с запросом текста)
  * (не имеет отношения к nc_search_context)
  */
 protected function document_set_context(nc_search_result_document $doc)
 {
     // служба поиска (напр. Гугль какой-нибудь), теоретически, может установить свойство context
     if (!$doc->get('context') && $this->should_highlight()) {
         $language = $this->get_query()->get('language');
         $doc->set('context', $this->highlight($doc->get('content'), $language, nc_search::get_setting('ResultContextMaxNumberOfWords')));
         $doc->set('title', $this->highlight($doc->get('title'), $language, nc_search::get_setting('ResultTitleMaxNumberOfWords')));
     }
     return $doc;
 }
Пример #2
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;
 }
Пример #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;
 }