我有300万件具有这种结构的物品:
{
"id": "some_id",
"title": "some_title",
"photos": [
{...},
{...},
...
]
}
某些项目可能包含空photos
字段:
{
"id": "some_id",
"title": "some_title",
"photos": []
}
我想按照照片的数量排序,导致没有照片的元素出现在列表的末尾。
我有一个有效的解决方案,但300万件物品的速度非常慢:
GET myitems/_search
{
"filter": {
...some filters...
},
"sort": [
{
"_script": {
"script": "_source.photos.size()",
"type": "number",
"order": "desc"
}
}
]
}
此查询执行55秒。如何优化此查询?
答案 0 :(得分:0)
正如评论中所建议的那样,添加一个包含照片数量的新字段将是最佳选择。有一种方法可以使用update by query plugin实现此而无需重新编制索引所有数据。
基本上,在安装插件后,您可以运行以下查询,所有文档都将获得该新字段。但是,请确保索引过程还填充新文档中的新字段:
curl -XPOST 'localhost:9200/myitems/_update_by_query' -d '{
"query" : {
"match_all" : {}
},
"script" : "ctx._source.nb_photos = ctx._source.photos.size();"
}'
运行完毕后,您只需使用以下内容对结果进行排序:
"sort": {"nb_photos": "desc"}
注意:要使此插件正常工作,需要scripting enabled,因为您可以使用排序脚本,所以已经是您的情况,但我只是为了完整性而提到这一点。
答案 1 :(得分:0)
使用Transform指令解决了问题。现在我有一个映射:
PUT /myitems/_mapping/lol
{
"lol" : {
"transform": {
"lang": "groovy",
"script": "ctx._source['has_photos'] = ctx._source['photos'].size() > 0"
},
"properties" : {
... fields ...
"photos" : {"type": "object"},
"has_photos": {"type": "boolean"}
... fields ...
}
}
}
现在我可以通过照片存在对项目进行排序:
GET /test/_search
{
"sort": [
{
"has_photos": {
"order": "desc"
}
}
]
}
不幸的是,这将导致完全重新索引。