对于这种弹性搜索,我还比较陌生。因此,我以下述方式将数据存储在弹性搜索中:
[{
"name": "user1",
"city": [{
"name": "city1",
"count": 18
},{
"name": "city2",
"count": 15
},{
"name": "city3",
"count": 10
},{
"name": "city4",
"count": 5
}]
},{
"name": "user2",
"city": [{
"name": "city2",
"count": 2
},{
"name": "city5",
"count": 5
},{
"name": "city6",
"count": 8
},{
"name": "city8",
"count": 15
}]
},{
"name": "user3",
"city": [{
"name": "city1",
"count": 2
},{
"name": "city5",
"count": 5
},{
"name": "city7",
"count": 28
},{
"name": "city2",
"count": 1
}]
}]
因此,我想做的是,找出城市列表中具有“ city2”的用户,并根据“ city2”的“计数”对数据进行排序。 >
这是我查询过的内容:
{
"sort": [{
"city.count": {
"order" : "desc"
}
}],
"query": {
"bool": {
"must": [
{"match": {"city.name": "city2"}}
]
}
}
}
所以我无法弄清楚排序方式! 排序部分正在基于过滤器考虑所有城市的所有“计数”值,但我只希望仅基于“ city2”的“计数”来执行排序。
任何帮助将不胜感激。预先感谢。
答案 0 :(得分:1)
由于字段city
是object
而不是nested object
,因此您无法实现的目标。这样做的原因是,当您将一个字段定义为object
时,弹性将每个对象字段的值展平为一个数组。所以,
"city": [
{
"name": "city1",
"count": 18
},
{
"name": "city2",
"count": 15
},
{
"name": "city3",
"count": 10
},
{
"name": "city4",
"count": 5
}
]
的索引为:
"city.name" : ["city1", "city2", "city3", "city4"]
"city.count": [18, 15, 10, 5]
如您所见,由于对象的弹性索引方式丢失了每个城市与其城市数量之间的关系。
因此,每当要保留关系时,都应将字段定义为nested
类型。
{
"city": {
"type": "nested",
"properties": {
"name": {
"type": "text"
},
"count": {
"type": "long"
}
}
}
}
然后可以使用此nested field进行排序。
{
"sort": [
{
"city.count": {
"order": "desc",
"mode": "avg",
"nested": {
"path": "city",
"filter": {
"match": {
"city.name": "city2"
}
}
}
}
}
],
"query": {
"bool": {
"must": [
{
"match": {
"city.name": "city2"
}
}
]
}
}
}
答案 1 :(得分:0)
达到目标会有些复杂。
首先,您的查询说您要获取其中带有“ city2”的文档。由于数组“ city”中的至少一个元素匹配,因此将返回整个文档。
问题是您只想返回city2的计数,而不是全部返回。这就是复杂的部分来了。
您可以遵循很多方法:
更改索引设计。与其拥有一系列用户,不如让每个用户拥有一个包含所有信息(包括访问过的城市)的文档。但是,“我只想要数组中的1个元素”问题仍然存在,但是您一次只能处理一个数组,而不是n。
您可以使用Painless仅带回该特定城市的数量,但这将意味着大量脚本编写。不要相信这个名字。无痛是非常痛苦的。
您可以带回所有元素,并在代码中进行过滤。例如,如果使用Python Elasticsearch Client,则可以执行查询,返回所有对象,并仅使用Python选择所需的元素。
不要考虑使用Terms aggregation。它将带回所有城市的总数,而无需与每个用户保持联系。这不是您想要做的。
希望这是有帮助的,很抱歉,我们无法直接解决问题:(