2012-03-20 58 views

回答

30

您可以使用唯一字段(例如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

+0

我会将字符串存储在客户端上吗?例如在一个cookie?因此,当用户呼叫第2页时,相同的顺序被保存下来了? – Yeggeps 2012-03-21 13:42:42

+0

应该生成salt字符串并存储在维护用户会话的图层上。它可以是您存储用户查询或当前显示的页码的相同位置。它也可以是cookie。 – imotov 2012-03-21 13:58:33

3

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

我已经在模型上有一个randomized_key。我也不需要为每个请求随机的命令,所以我做了一个预定的工作,每晚更新随机密钥,然后在Elasticssearch中按照该字段进行排序。

18

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" 
    } 
    } 
} 

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

+5

这是一个很好的通用解决方案。然而,最初的问题是要求“可选的种子允许娱乐随机顺序”。这就是所有复杂性来自的地方。 – imotov 2012-09-26 16:49:21

+0

是的,你完全正确。我的解决方案更适合标题“随机排序和分页Elasticsearch”。完全不能满足Yegegeps的需求。 – DavidGOrtega 2012-09-26 18:30:43

+3

基本的随机排序优秀的答案,谢谢 – Eva 2013-04-18 05:10:55

50

这应该是比上面两个答案相当快,并支持直播:

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

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

+1

感谢您的帮助。我认为答案会更清楚地表明,如果更新示例查询,random_score支持种子播种。 – 2017-02-21 10:48:51

+0

如果您使用过滤器,则不起作用。 – 2017-05-23 13:08:19

0

嗯,我一直在寻找这样做的,上面所有的方法似乎有点“太复杂“对于那些应该相对简单的事情来说。所以,我想出了好完美的作品,而不需要“走出心理”

我先执行_count查询然后用“开始”和兰特(0,$计数)

例如结合它的替代

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,这种方法可以用于任何示例。