Elasticsearch中的嵌套对象数

zlhcx6iw  于 2023-02-11  发布在  ElasticSearch
关注(0)|答案(2)|浏览(169)

寻找一种方法来获取嵌套对象的数量,用于查询、排序等。例如,给定以下索引:

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "some_id": {"type": "long"},
      "user": {
        "type": "nested",
        "properties": {
          "first": {
            "type": "keyword"
          },
          "last": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "some_id": 111,
  "user" : [
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}

如何按用户数过滤(如查询取所有用户数超过XX的单据)。
我想使用一个runtime_field,但这会产生一个错误:

GET my-index-000001/_search
{
  "runtime_mappings": {
    "num": {
      "type": "long",
      "script": {
        "source": "emit(doc['some_id'].value)"
      }
    },
    "num1": {
      "type": "long",
      "script": {
        "source": "emit(doc['user'].size())" // <- this breaks with "No field found for [user] in mapping"
      }
    }
  }
  ,"fields": [
    "num","num1"
  ]
}

可能使用聚合吗?
如果我能对结果进行排序(例如,所有超过XX的文档都按XX排序),我也会很高兴。
谢谢。

c6ubokkw

c6ubokkw1#

您无法 * 有效地 * 查询此内容
可以使用这个技巧,但我只会在您需要执行一些一次性获取时使用它,而不是在常规用例中使用,因为它使用params,因此当您有很多文档时会非常慢

{
  "query": {
    "function_score": {
      "min_score": 1,  # -> min number of nested docs to filter by
      "query": {
        "match_all": {}
      },
      "functions": [
        {
          "script_score": {
            "script": "params._source['user'].size()"
          }
        }
      ],
      "boost_mode": "replace"
    }
  }
}

它基本上为每个文档计算一个新的分数,其中分数等于users数组的长度,然后从返回中删除min_score下的所有文档

vnzz0bqm

vnzz0bqm2#

最好的方法是在索引时添加一个userCount字段(因为您知道有多少元素),然后使用range查询来查询该字段,非常简单、高效和快速。
嵌套数组的每个元素本身就是一个文档,因此不能通过根级文档进行查询。
如果无法重新创建索引,可以利用_update_by_query端点添加该字段:

POST my-index-000001/_update_by_query?wait_for_completion=false
{
  "script": {
    "source": """
     ctx._source.userCount = ctx._source.user.size()
    """
  }
}

相关问题