如何根据筛选数据对弹性搜索中的数据进行排序

How to sort data in elastic search based on the filter data

我对这个弹性搜索比较陌生。所以我以下面提到的方式将数据存储在弹性搜索中:

[{
    "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" 的用户,然后 根据 "count" 的 "count" 对数据进行排序26=].

这是我尝试过的查询:

{
    "sort": [{
        "city.count": {
            "order" : "desc"
        }
    }],
    "query": {
        "bool": {
            "must": [
                 {"match": {"city.name": "city2"}}
            ]
        }
    }
}

所以我不知道排序部分该怎么做! 排序部分正在考虑基于过滤器的所有城市的所有 "count" 值,但我只想根据 "city2" 的 "count" 进行排序.

如有任何帮助,我们将不胜感激。提前致谢。

实现目标会有点复杂。

首先,您的查询表明您想获取其中包含 "city2" 的文档。由于数组 "city" 中至少有一个元素匹配,因此整个文档将被 returned.

问题是您只想 return city2 的计数,而不是所有城市的计数。这就是复杂部分的来源。

有很多路径可供选择:

  1. 更改您的索引设计。与其拥有一系列用户,不如为每个用户提供一个文档,其中包含他们的所有信息,包括他们访问过的城市。但是,"I only want 1 element from the array"的问题还是会存在,只是你一次只会打一个数组,而不是n个。

  2. 您可以使用 Painless 仅返回特定城市的计数,但这意味着需要编写大量脚本。不要相信这个名字。无痛是很痛的。

  3. 您可以带回所有元素并在您的代码中进行过滤。例如,如果您使用 Python Elasticsearch Client,您可以执行查询,return 所有对象,并且仅使用 Python.

  4. 来选择想要的元素

不考虑使用 Terms aggregation。它将带回所有城市的总计数,而无需与每个用户建立关系。而这不是你想要做的。

希望这对您有所帮助,很抱歉我们无法获得直接的解决方案:(

由于字段 cityobject 而不是 nested object,因此您想要实现的目标是不可能的。这样做的原因是,当您将一个字段定义为 object 时,elastics 将每个对象字段值展平为一个数组。所以,

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