0

我对这种弹性搜索比较陌生。因此,我以下述方式将数据存储在弹性搜索中:

[{
    "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”的“count”对数据进行排序。

这是我尝试过的查询:

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

所以我无法弄清楚排序部分如何去做! 排序部分正在考虑基于过滤器的所有城市的所有“计数”值,但我只想根据“city2”的“计数”进行排序。

任何形式的帮助将不胜感激。提前致谢。

4

2 回答 2

1

由于该领域cityisobject和 not 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"
      }
    }
  }
}

然后可以通过使用这个嵌套字段来实现排序。

{
  "sort": [
    {
      "city.count": {
        "order": "desc",
        "mode": "avg",
        "nested": {
          "path": "city",
          "filter": {
            "match": {
              "city.name": "city2"
            }
          }
        }
      }
    }
  ],
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "city.name": "city2"
          }
        }
      ]
    }
  }
}
于 2019-08-21T04:09:56.723 回答
0

达到你的目标会有点复杂。

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

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

您可以遵循很多路径:

  1. 改变你的索引设计。与其拥有一组用户,不如让每个用户拥有一个包含他们所有信息的文档,包括他们访问过的城市。但是,“我只想要数组中的 1 个元素”问题仍然存在,但是您一次只会与一个数组而不是 n 战斗。

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

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

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

希望这是有帮助的,很抱歉我们无法得到一个直接的解决方案:(

于 2019-08-20T18:54:34.207 回答