【问题标题】:Random order & pagination Elasticsearch随机排序和分页 Elasticsearch
【发布时间】:2012-04-05 11:46:45
【问题描述】:

this issue 是一种使用可选种子进行排序的功能请求,允许重新生成随机顺序。

我需要能够对随机排序的结果进行分页。 Elasticsearch 0.19.1 怎么能做到这一点?

谢谢。

【问题讨论】:

    标签: random pagination elasticsearch


    【解决方案1】:

    这应该比上面两个答案都快得多,并且支持播种:

    curl -XGET 'localhost:9200/_search' -d '{
      "query": {
        "function_score" : {
          "query" : { "match_all": {} },
          "random_score" : {}
        }
      }
    }';
    

    见:https://github.com/elasticsearch/elasticsearch/issues/1170

    【讨论】:

    • 感谢您的帮助。如果您更新示例查询,我认为答案会更清楚地表明 random_score 支持播种。
    • @MbRostami 对于必须添加的过滤器"boost_mode": "replace",,请参阅stackoverflow.com/a/48338880/1194525
    【解决方案2】:

    您可以使用唯一字段(例如 id)和随机盐的哈希函数进行排序。根据结果​​的真正随机性,您可以执行以下原始操作:

    {
      "query" : { "query_string" : {"query" : "*:*"} },
      "sort" : {
        "_script" : { 
            "script" : "(doc['_id'].value + salt).hashCode()",
            "type" : "number",
            "params" : {
                "salt" : "some_random_string"
            },
            "order" : "asc"
        }
      }
    }
    

    或者像

    这样复杂的东西
    {
      "query" : { "query_string" : {"query" : "*:*"} },
      "sort" : {
        "_script" : { 
            "script" : "org.elasticsearch.common.Digest.md5Hex(doc['_id'].value + salt)",
            "type" : "string",
            "params" : {
                "salt" : "some_random_string"
            },
            "order" : "asc"
        }
      }
    }
    

    第二个示例会产生更多随机结果,但速度会慢一些。

    为了使这种方法起作用,必须存储字段_id。否则,查询将失败并显示NullPointerException

    【讨论】:

    • 那我会在客户端存储字符串吗?例如在 cookie 中?这样当用户调用第 2 页时,会保留相同的顺序?
    • 盐字符串应该被生成并存储在维护用户会话的层上。它可以是您存储用户查询或当前显示的页码的同一位置。它也可以是 cookie。
    【解决方案3】:

    来自 imotov 的好解决方案。

    这里有一些更简单的东西,您不需要依赖文档属性:

    {
      "query" : { "query_string" : {"query" : "*:*"} },
      "sort" : {
        "_script" : { 
            "script" : "Math.random()",
            "type" : "number",
            "params" : {},
            "order" : "asc"
        }
      }
    }
    

    如果您想设置一个类似于以下内容的范围:

    {
      "query" : { "query_string" : {"query" : "*:*"} },
      "sort" : {
        "_script" : { 
            "script" : "Math.random() * (myMax - myMin) + myMin",
            "type" : "number",
            "params" : {},
            "order" : "asc"
        }
      }
    }
    

    用适当的值替换最大值和最小值。

    【讨论】:

    • 这是一个很好的通用解决方案。但是,最初的问题是要求“允许重新生成随机顺序的可选种子”。这就是所有复杂性的来源。
    • 是的,你完全正确。我的解决方案更适合标题“随机顺序和分页 Elasticsearch”。完全无法满足 Yeggeps 的需求。
    • 很好的答案,但不幸的是,这也不能消除脚本排序的开销......仍然会为我们对 2M 文档的查询添加 > 1s。
    • 每 100 个结果(大小为 20)我得到约 10 个重复项。如何消除重复?
    【解决方案4】:

    我最终解决的问题与 imotov 建议的略有不同。由于我有多个客户端,我不想在每个客户端上实现围绕盐字符串的逻辑。

    我已经在模型上有了一个随机键。我也不需要每个请求的顺序都是随机的,所以我安排了一个工作,每晚更新随机键,然后在 Elasticssearch 中按该字段排序。

    【讨论】:

      【解决方案5】:

      嗯,我正在考虑这样做,但上面的所有方法对于应该相对简单的事情来说似乎有点“太复杂”了。所以我想出了一个效果很好的替代方案,而不需要“精神上的”

      我先执行 _count 查询,然后将其与“Start”和 rand(0,$count) 结合起来

      例如

      JSONArray = array of json to send to ElasticSearch
      $total_results = $ElasticSearchClient->count(JSONArray)
      $start = rand(0, $total_results)
      JSONArray['body']['from'] = $start;
      $ElasticSearchClient->search(JSONArray);
      

      上述例子的假设:

      • 您正在运行 PHP
      • 您也在使用 PHP 客户端

      但是您不需要使用 PHP 来执行此操作,该方法适用于任何示例。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-10-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-04
        • 1970-01-01
        • 2015-10-14
        相关资源
        最近更新 更多