Elasticseach 随机抽取记录

业务场景中,特别是审核相关的一些场景,经常会有对数据进行抽取评估的需求。抽取的规则需要尽可能的平均。

当数据量小的时候,用mysql的 order by rand() 即可实现,但当数据量非常大的时候,该方法就不是很适用了,会非常的慢。

此时我们就可以借助其他的一些工具,比如elasticsearch (如果你业务中已经使用了的话,否则可以考虑其他的技术方案)

如果运用elasticsearch来实现随机抽取的目的呢?跟mysql的 order by rand() 采用一样的逻辑,elasticsearch 也支持自定义的排序规则。

如下, 设置排序规则为 (doc[‘_id’].value + params.random_salt).hashCode(), params.random_salt 为自己设置的加密盐,如我这里设置的是 random_salt = md5(time())

{
    "_source":{
        "include":[
            "id"
        ]
    },
    "sort":{
        "_script":{
            "script":{
                "inline":"(doc['_id'].value + params.random_salt).hashCode()",
                "params":{
                    "random_salt":"50715bab076c6c3376556c85c8236723"
                }
            },
            "type":"number",
            "order":"asc"
        }
    },
    "size":10,
    "query":{
        "bool":{
            "filter":[
                {
                    "range":{
                        "create_time":{
                            "gte":1609731331,
                            "lte":1611135233
                        }
                    }
                }
            ]
        }
    }
}

以上检索条件会查询出满足条件的10条随机记录,这是运用了search, 如果想要抽取特别多的数据的话,scroll也同样适用。当然你也可以选择其他的排序规则,只要确保该规则计算的结果尽可能的随机即可。

注意:如果是想要多页的获取数据的话,必须保证多页的检索条件的sort是同样的,否则就会出现检索出相同的数据(因为每次都是按照不同的排序规则排序,获取该排序规则上,该页的数据)。当然,如果只是想要抽取少量的数据,无需多页获取的话,也可以直接使用 “script”: “Math.random()” 来获取随机数据。

{
    "_script":{
        "script":"Math.random()",
        "type":"number",
        "order":"asc"
    }
}

1 评论
最新
最旧 最多投票
内联反馈
查看所有评论
滚动至顶部