2015-01-20 3 views
6

Я создал поисковую систему для поиска всех документов в моем индексе elasticsearch. Когда пользователь нажимает на документ на странице результатов поиска, он покидает текущую страницу и открывает страницу удаления этого документа.Elasticsearch - предыдущая/следующая функциональность

Теперь id как реализовать небольшую навигацию по документу на этой странице подробностей, но я не могу понять, как создать что-то подобное с помощью elasticsearch. Id нравится иметь предыдущий документ и следующую ссылку документа поверх этой подробной страницы документа.

Моя идея состояла в том, чтобы сохранить все возвращенные документы в cookie сеанса или что-то еще, чтобы запомнить следующий и предыдущий документ этого текущего поиска. Но у меня также есть разбиение на страницы на этой странице результатов поиска. Когда пользователь выбирает последний документ на странице результатов, следующая ссылка не будет работать, потому что мой текущий поиск еще не получил никаких документов.

Является ли это общей проблемой или конкретным? У кого-нибудь из вас появилась идея, которая могла бы помочь мне решить эту проблему? Возможно, scroll-API?

Благодаря

+0

Вы получили решение? – richardwhatever

+0

есть. Я просто сохраняю запрос в сеансе и вычисляю следующий и предыдущий элемент. – Stillmatic1985

+0

@ Stillmatic1985: написано: «Прокрутка не предназначена для запросов пользователя в реальном времени». Можете ли вы объяснить свой алгоритм и решение, (было бы круто поделиться) Я не вижу, как это работает. – COil

ответ

-1

Если ваши документы с помощью последовательного _id, то вы можете просто сделать текущий документ _id + 1 и запросить его снова.

+0

Если вы работаете по ID только по возрастанию. – datashaman

1

Следующие работы прекрасно для меня. Убедитесь, что вы используете регулярно форматированный список sort определений, как это:

function getSortDefinitions() { 
    return [ 
     'newest' => [ 
      [ 'created_at' => 'desc' ], 
      [ 'id' => 'desc' ], 
     ], 
     'oldest' => [ 
      [ 'created_at' => 'asc' ], 
      [ 'id' => 'asc' ], 
     ] 
     'highest' => [ 
      [ 'price' => 'desc' ], 
      [ 'created_at' => 'desc' ], 
      [ 'id' => 'desc' ], 
     ], 
     'lowest' => [ 
      [ 'price' => 'asc' ], 
      [ 'created_at' => 'asc' ], 
      [ 'id' => 'asc' ], 
     ], 
    ]; 
} 

в стороне: Добавление id делает ResultSet имеет предсказуемый порядок для записей с тем же временным метким. Это часто случается при тестировании светильников, где все записи сохраняются одновременно.

Теперь, когда кто-то ищет, они обычно выбирают несколько фильтров, возможно, запрос и определенно порядок сортировки. Создать таблицу, которая хранит это так, вы можете создать контекст поиска работы с:

create table search_contexts (
    id int primary, 
    hash varchar(255) not null, 
    query varchar(255) not null, 
    filters json not null, 
    sort varchar(255) not null, 

    unique search_contexts_hash_uk (hash) 
); 

использовать что-то вроде следующего в вашем языке выбора для вставки и получить ссылку на поиск контекста:

function saveSearchContext($query, $filters, $sort) 
{ 
    // Assuming some magic re: JSON encoding of $filters 
    $hash = md5(json_encode(compact('query', 'filters', 'sort'))); 
    return SearchContext::firstOrCreate(compact('hash', 'query', 'filters', 'sort')); 
} 

Обратите внимание, что мы вставляем только контекст поиска, если его уже нет с теми же параметрами. Таким образом, мы получаем одну уникальную строку для каждого поиска. Вы можете выбрать, чтобы быть перегруженным томом и сохранить один за поиск. Если вы решите это сделать, используйте uniqid вместо md5 и просто создайте запись.

На индексной странице результатов, каждый раз, когда вы создаете ссылку на страницу с описанием, использовать хэш в качестве параметра запроса, как это:

http://example.com/details/2456?search=7ddf32e17a6ac5ce04a8ecbf782ca509 

В вашей детализации код страницы, сделать что-то вроде этого:

function getAdjacentDocument($search, $documentId, $next = true) { 
    $sortDefinitions = getSortDefinitions(); 

    if (!$next) { 
     // Reverse the sort definitions by looping through $sortDefinitions 
     // and swapping asc and desc around 
     $sortDefinitions = array_map($sortDefinitions, function ($defn) { 
      return array_map($defn, function ($array) { 
       $field = head(array_keys($array)); 
       $direction = $array[$field]; 

       $direction = $direction == 'asc' ? 'desc' : 'asc'; 

       return [ $field => $direction ]; 
      }); 
     }); 
    } 

    // Add a must_not filter which will ensure that the 
    // current page's document ID is *not* in the results. 
    $filters['blacklist'] = $documentId; 

    $params = [ 
     'body' => [ 
      'query' => generateQuery($search->query, $filters), 
      'sort' => $sortDefinitions[$sort], 

      // We are only interested in 1 document adjacent 
      // to this one, limit results 
      'size' => 1 
     ] 
    ]; 

    $response = Elasticsearch::search($params); 

    if ($response['found']) { 
     return $response['hits']['hits'][0]; 
    } 
} 

function getNextDocument($search, $documentId) { 
    return getAdjacentDocument($search, $documentId, true); 
} 

function getPreviousDocument($search, $documentId) { 
    return getAdjacentDocument($search, $documentId, false); 
} 

// Retrieve the search context given it's hash as query parameter 
$searchContext = SearchContext::whereHash(Input::query('search'))->first(); 

// From the route segment 
$documentId = Input::route('id'); 

$currentDocument = Elasticsearch::get([ 
    'id' => $documentId, 
    'index' => 'documents' 
]); 

$previousDocument = getPreviousDocument($searchContext, $documentId); 
$nextDocument = getNextDocument($searchContext, $documentId); 

Ключом к этой технике является то, что вы создаете два запроса в дополнение к get для подробной записи.

Один поиск идет вперед от этой записи, другие идет в обратном направлении от этой записи, данного тот же контекстный поиск в обеих случаях, так что они работают в соответствии с Афоризмом.

В обоих случаях вы берете первую запись, которая составляет , а не нашей текущей записи, и она должна соответствовать .

Смежные вопросы