Я создал поисковую систему для поиска всех документов в индексе elasticsearch. Когда пользователь нажимает на документ на странице результатов поиска, он покидает текущую страницу и открывает страницу удаления этого документа.
Теперь id как бы реализовать небольшую навигацию по документу на этой странице подробностей, но я не могу понять, как создать что-то подобное с помощью elasticsearch. Id нравится иметь предыдущий документ и следующую ссылку документа поверх этой подробной страницы документа.
Моя идея состояла в том, чтобы сохранить все возвращенные документы в cookie сеанса или что-то еще, чтобы запомнить следующий и предыдущий документ этого текущего поиска. Но у меня также есть разбиение на страницы на этой странице результатов поиска. Когда пользователь выбирает последний документ на странице результатов, следующая ссылка не будет работать, потому что мой текущий поиск еще не получил никаких документов.
Является ли это общей проблемой или конкретной? У кого-нибудь из вас появилась идея, которая могла бы помочь мне решить эту проблему? Может быть, scroll-API
?
благодаря
Следующее прекрасно работает для меня. Убедитесь, что вы используете регулярно отформатированный список определений 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
делает набор результатов предсказуемым упорядочением для записей с одинаковой меткой времени. Это часто случается при тестировании светильников, где все записи сохраняются одновременно.
Теперь, когда кто-то ищет, они обычно выбирают несколько фильтров, возможно, запрос и определенно порядок сортировки. Создайте таблицу, которая хранит это, чтобы вы могли создать контекст поиска для работы с:
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
для подробной записи.
Один поиск идет вперед из этой записи, другой идет назад от этой записи, учитывая тот же контекст поиска в обоих случаях, поэтому они работают в соответствии с eachother.
В обоих случаях вы берете первую запись, которая не является нашей текущей записью, и она должна быть правильной.
Если ваши документы используют последовательный _id, вы можете просто сделать текущий документ _id + 1 и запросить его снова.