【问题标题】:Elastic Search Querying/filtering nested arrays弹性搜索查询/过滤嵌套数组
【发布时间】:2015-11-18 19:45:34
【问题描述】:

我在 ES 中的索引 test_agg 上存储了以下类型的嵌套数据。

{
  "Date": "2015-10-21",
  "Domain": "abc.com",
  "Processed_at": "10/23/2015 9:47",
  "Events": [
    {
      "Name": "visit",
      "Count": "188",
      "Value_Aggregations": [
        {
          "Value": "red",
          "Count": "100"
        }
      ]
    },
    {
      "Name": "order_created",
      "Count": "159",
      "Value_Aggregations": [
        {
          "Value": "$125",
          "Count": "50"
        }
      ]
   },
 ]
}

嵌套项的映射是

curl -XPOST localhost:9200/test_agg/nested_evt/_mapping -d '{
"nested_evt":{
"properties":{
   "Events": {
       "type": "nested"
    }
   }
  }
}'

我正在尝试使用以下查询获取“Events.Count”和“Events.Value_Aggregations.Count”,其中 Events.Name='Visit'

{
 "fields" : ["Events.Count","Events.Value_Aggregations.Count"]
  "query": {
     "filtered": {
        "query": {
            "match": { "Domain": "abc.com" }
        },
        "filter": {
            "nested": {
                "path": "Events",
                "query": {
                     "match": { "Events.Name": "visit" }
                },
              }
          }
      }
   }
 }

而不是产生单个值

Events.Count=[188] Events.Value_Aggregations.Count=[100]

它给了

Events.Count=[188,159] Events.Value_Aggregations.Count=[100,50]

获得所需输出的确切查询结构是什么?

【问题讨论】:

    标签: elasticsearch


    【解决方案1】:

    所以这里的问题是您正在应用的nested 过滤器根据嵌套子 文档的属性选择 文档。因此 ES 找到与您的查询匹配的父文档(基于文档的嵌套子级)。然后,由于您指定了"fields",它不会返回整个文档,而是仅选择您要求的那些字段。这些字段恰好是嵌套字段,并且由于父文档有两个嵌套的子文档,它会为您指定的字段分别找到两个值并返回它们。据我所知,没有办法改为返回子文档,至少使用 nested 架构。

    此问题的一个解决方案是改用parent/child relationship,然后您可以将has_parent 查询与其他过滤器结合使用,针对子类型来获得您想要的。只要架构架构不与您的其他需求冲突,这可能是一种更简洁的方法。

    但是,有一种方法可以使用您当前的架构,结合nested aggregationfilter aggregation 来完成您的要求。这有点涉及(在这种情况下有点模棱两可;请参阅下面的解释),但这是查询:

    POST /test_index/_search
    {
       "size": 0,
       "query": {
          "filtered": {
             "query": {
                "match": {
                   "Domain": "abc.com"
                }
             },
             "filter": {
                "nested": {
                   "path": "Events",
                   "query": {
                      "match": {
                         "Events.Name": "visit"
                      }
                   }
                }
             }
          }
       },
       "aggs": {
          "nested_events": {
             "nested": {
                "path": "Events"
             },
             "aggs": {
                "filtered_events": {
                   "filter": {
                      "term": {
                         "Events.Name": "visit"
                      }
                   },
                   "aggs": {
                      "events_count_terms": {
                         "terms": {
                            "field": "Events.Count"
                         }
                      },
                      "value_aggregations_count_terms": {
                         "terms": {
                            "field": "Events.Value_Aggregations.Count"
                         }
                      }
                   }
                }
             }
          }
       }
    }
    

    返回:

    {
       "took": 3,
       "timed_out": false,
       "_shards": {
          "total": 1,
          "successful": 1,
          "failed": 0
       },
       "hits": {
          "total": 1,
          "max_score": 0,
          "hits": []
       },
       "aggregations": {
          "nested_events": {
             "doc_count": 2,
             "filtered_events": {
                "doc_count": 1,
                "value_aggregations_count_terms": {
                   "doc_count_error_upper_bound": 0,
                   "sum_other_doc_count": 0,
                   "buckets": [
                      {
                         "key": "100",
                         "doc_count": 1
                      }
                   ]
                },
                "events_count_terms": {
                   "doc_count_error_upper_bound": 0,
                   "sum_other_doc_count": 0,
                   "buckets": [
                      {
                         "key": "188",
                         "doc_count": 1
                      }
                   ]
                }
             }
          }
       }
    }
    

    警告:我不清楚你是否真的需要我在这里展示的"query""filter": { "nested": { ... } } 子句。如果这部分以有用的方式过滤掉父文档,那么您需要它。如果您的唯一目的是选择要从中返回字段的嵌套子文档,那么这里是多余的,因为 filter 聚合正在处理该部分。

    这是我用来测试它的代码:

    http://sense.qbox.io/gist/dcc46e50117031de300b6f91c647fe9b729a5283

    【讨论】:

    • 感谢您的详细回答。我尝试了父/子查询,它可以正常工作并产生我预期的输出。
    【解决方案2】:

    这是产生我想要的输出的父/子关系查询

    {
      "query": {
      "filtered": {
        "query": {
              "bool": {"must": [
              {"term": {"Name": "visit"}}
             ]}
        },
        "filter":{
        "has_parent": {
          "type": "domain_info",
          "query" : {
            "filtered": {
              "query": { "match_all": {}},
              "filter" : {
                "and": [
                  {"term": {"Domain": 'abc.com'}}
    
                ]
              }
            }
          }
         }
        }
      }
     }
    }
    

    【讨论】:

    • 这可能更有意义。我不知道你能不能走这条路。
    猜你喜欢
    • 1970-01-01
    • 2020-02-07
    • 1970-01-01
    • 1970-01-01
    • 2021-09-01
    • 2015-09-24
    • 2020-12-27
    • 2023-01-10
    • 2015-01-25
    相关资源
    最近更新 更多