弹性搜索查询/过滤嵌套数组

时间:2015-11-17 18:01:38

标签: elasticsearch

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

select distinct on (value) id, value, name, date
from the_table
order by value, date;

嵌套项的映射是

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

我正在努力获得" Events.Count"和" Events.Value_Aggregations.Count"其中Events.Name ='访问'使用以下查询

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

而不是产生单一值

  

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

它给出了

  

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

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

2 个答案:

答案 0 :(得分:5)

因此,问题在于您应用的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
                  }
               ]
            }
         }
      }
   }
}

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

以下是我用来测试它的代码:

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

答案 1 :(得分:1)

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

{
  "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'}}

            ]
          }
        }
      }
     }
    }
  }
 }
}