如何按嵌套类型的数组大小过滤?

问题描述 投票:1回答:1

假设我具有以下类型:

{
    "2019-11-04": {
        "mappings": {
            "_doc": {
                "properties": {
                    "labels": {
                        "type": "nested",
                        "properties": {
                            "confidence": {
                                "type": "float"
                            },
                            "created_at": {
                                "type": "date",
                                "format": "strict_date_optional_time||date_time||epoch_millis"
                            },
                            "label": {
                                "type": "keyword"
                            },
                            "updated_at": {
                                "type": "date",
                                "format": "strict_date_optional_time||date_time||epoch_millis"
                            },
                            "value": {
                                "type": "keyword",
                                "fields": {
                                    "numeric": {
                                        "type": "float",
                                        "ignore_malformed": true
                                    }
                                }
                            }
                        }
                    },
                    "params": {
                        "type": "object"
                    },
                    "type": {
                        "type": "keyword"
                    }
                }
            }
        }
    }
}

而且我想按labels数组的大小/长度进行过滤。我已经尝试了以下(as the official docs suggest

{
  "error": {
    "root_cause": [
      {
        "type": "script_exception",
        "reason": "runtime error",
        "script_stack": [
          "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:81)",
          "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:39)",
          "doc['labels'].size > 10",
          "    ^---- HERE"
        ],
        "script": "doc['labels'].size > 10",
        "lang": "painless"
      }
    ],
    "type": "search_phase_execution_exception",
    "reason": "all shards failed",
    "phase": "query",
    "grouped": true,
    "failed_shards": [
      {
        "shard": 0,
        "index": "2019-11-04",
        "node": "kk5MNRPoR4SYeQpLk2By3A",
        "reason": {
          "type": "script_exception",
          "reason": "runtime error",
          "script_stack": [
            "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:81)",
            "org.elasticsearch.search.lookup.LeafDocLookup.get(LeafDocLookup.java:39)",
            "doc['labels'].size > 10",
            "    ^---- HERE"
          ],
          "script": "doc['labels'].size > 10",
          "lang": "painless",
          "caused_by": {
            "type": "illegal_argument_exception",
            "reason": "No field found for [labels] in mapping with types []"
          }
        }
      }
    ]
  },
  "status": 500
}
elasticsearch elasticsearch-6
1个回答
0
投票

得到该错误的原因仅仅是因为Nested Documents本身作为单独的文档存储,如上述链接中所述:

内部,嵌套对象将数组中的每个对象都索引为单独的隐藏文档,这意味着每个嵌套对象都可以使用嵌套查询独立于其他查询:

您需要执行的是在嵌套查询中执行脚本。为了简单起见,我创建了一个简单的映射,文档,查询和示例响应:

映射:

PUT my_sample_index
{
  "mappings": {
    "properties": {
      "myfield": {
        "type": "nested",
        "properties": {
          "label": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

样本文件:

POST my_sample_index/_doc/1
{
  "myfield": {
    "label": ["New York", "LA", "Austin"]
  }
}

POST my_sample_index/_doc/2
{
  "myfield": {
    "label": ["London", "Leicester"]
  }
}

查询:

POST my_sample_index/_search
{
  "_source": "*", 
  "query": {
    "bool": {
      "must": [
        {
          "nested": {                      <---- Actual Logic you are looking for
            "path": "myfield",
            "query": {
              "script": {
                "script": "doc['myfield.label'].size() > 2"      
              }
            }
          }
        }
      ]
    }
  },
  "script_fields": {                     <----- Added this to help you know size value
    "label_size": {
        "script": {
            "lang": "painless",
            "source": "params['_source']['myfield']['label'].size()"
        }
    }
  }
}

您正在寻找的核心逻辑是在Nested Query中。

[请注意,我在上面的查询中提到了一个单独的Script Field部分,只是为了让您对响应的大小有所了解。

将此字段视为类似于SQL中的别名,它在ES中不存在,而仅在运行时创建。

响应:

{
  "took" : 4,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "my_sample_index",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "myfield" : {
            "label" : [
              "New York",
              "LA",
              "Austin"
            ]
          }
        },
        "fields" : {
          "label_size" : [          <--- Script Field value to help you know the size
            3
          ]
        }
      }
    ]
  }
}

重要注意事项:一种更好的方法或我建议的方法是使用独立字段中的字段大小重新编制文档的索引,并且应在过滤器查询中使用该字段以帮助您得到你想要的。不推荐使用无痛脚本,因为它会导致性能问题。

© www.soinside.com 2019 - 2024. All rights reserved.