弹性搜索 - 上一个/下一个功能 [英] Elasticsearch - previous/next functionality

查看:141
本文介绍了弹性搜索 - 上一个/下一个功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个搜索引擎来搜索我的弹性搜索索引中的所有文档。当用户点击搜索结果页面上的文档时,他离开当前页面并打开该文档的删除页面。

I created a search engine to search all documents in my elasticsearch index. When a user hits a document on the searchengine resultpage he leaves the current page and opens the deatailpage of that document.

现在,我们希望在该细节上实现一点文档导航页面,但我不知道如何使用弹性搜索创建这样的东西。 Id喜欢在该文档详细信息页面之前拥有以前的文档和下一个文档链接。

Now id like to implement a little document navigation on that detail page but i cant figure out how to create something like this with elasticsearch. Id like to have a previous document and a next document link on top of that document detail page.

我的想法是将所有返回的文档保存在会话cookie或其他内容中记住当前搜索的下一个和上一个文档。但我也有一个分页的这个搜索结果页。当用户在结果页面上选择最后一个文档时,下一个链接不会工作,因为我当前的搜索没有任何更多的文档。

My idea was to save all returned documents in a session cookie or something else to remember the next and the previous document on that current search. But i also have a pagination on that searchengine resultpage. When a user selects the last document on a resultpage the next link wouldnt work because my current search hasnt got any more documents.

这是一个常见的问题还是具体的?任何人有一个想法可以帮助我解决这个问题?
也许 scroll-API

Is this a common problem or to specific? Anybody of you got an idea which could help me to solve that problem? Maybe the scroll-API?

谢谢

推荐答案

以下作品对我来说非常棒。确保您使用的定期格式化列表 sort 定义如下:

The following works beautifully for me. Ensure that you are using a regularly formatted list of sort definitions like this:

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 使结果集对于具有相同时间戳的记录具有可预测的排序。这样的事情经常发生在测试夹具中,记录全部同时被保存。

An aside: Adding id makes the resultset have predictable ordering for records with the same timestamp. This happens often with testing fixtures where the records are all saved at the same time.

现在每当有人搜索时,他们通常会选择一些过滤器,也许是一个查询排序顺序。创建一个存储此表的表,以便您可以生成一个搜索上下文来处理:

Now whenever someone searches, they have usually selected a few filters, perhaps a query and definitely a sort order. Create a table that stores this so you can generate a search context to work with:

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)
);

使用您所选语言的以下内容插入并获取对搜索上下文的引用:

Use something like the following in your language of choice to insert and get a reference to the search context:

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 ,只需创建记录。

Notice that we only insert a search context if there isn't one already there with the same parameters. So we end up with one unique row per search. You may choose to be overwhelmed by the volume and save one per search. If you choose to do that, use uniqid instead of md5 and just create the record.

在结果索引页上,无论何时生成到详细信息页面的链接,使用哈希作为这样的查询参数:

On the results index page, whenever you generate a link to the detail page, use the hash as a query parameter like this:

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



In your detail page code, do something like this:

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);

这种技术的关键是除了
之外,您还会生成两个搜索, code>获得的详细记录。

The key to this technique is that you are generating two searches in addition to the get for the detail record.

一个搜索从该记录转发,另一个从该记录向后退,$在这两种情况下,b $ b 给出相同的搜索上下文,所以它们与eachother一致。

One search goes forwards from that record, the other goes backwards from that record, given the same search context in both cases so they work in line with eachother.

在这两种情况下,您都可以获得第一条记录那不是我们目前的记录,而且
是正确的。

In both cases, you take the first record that is not our current record, and it should be correct.

这篇关于弹性搜索 - 上一个/下一个功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆