2014-11-04 3 views
9

У меня возникла проблема с агрегированием результатов после их фильтрации. Я думаю, что нахожусь на правильном пути, но чувствую, что я преследую свой хвост.ElasticSearch - фильтрация вложенной агрегирования

Вот как это выглядит:

PUT /my_index 
{ 
    "mappings": { 
    "reporting": { 
     "properties": { 
     "events": { 
      "type": "nested", 
      "properties": { 
      "name": { "type": "string", "index" : "not_analyzed" }, 
      "date": { "type": "date" } 
      } 
     } 
     } 
    } 
    } 
} 

Итак, мой документ выглядит следующим образом:

{ 
    "events": [ 
    { "name": "INSTALL", "date": "2014-11-01" }, 
    { "name": "UNINSTALL", "date": "2014-11-03" }, 
    { "name": "INSTALL", "date": "2014-11-04" }, 
    ... 
    ] 
} 

Теперь, когда I индекс некоторые данные, например:

PUT /my_index/reporting/1 
{ 
    "events": [ 
    { 
     "name": "INSTALL", 
     "date": "2014-11-01" 
    }, 
    { 
     "name": "UNINSTALL", 
     "date": "2014-11-05" 
    } 
] 
} 

PUT /my_index/reporting/2 
{ 
    "events": [ 
    { 
     "name": "INSTALL", 
     "date": "2014-11-01" 
    }, 
    { 
     "name": "UNINSTALL", 
     "date": "2014-11-03" 
    } 
] 
} 

PUT /my_index/reporting/3 
{ 
    "events": [ 
    { 
     "name": "INSTALL", 
     "date": "2014-11-01" 
    }, 
    { 
     "name": "UNINSTALL", 
     "date": "2014-11-02" 
    } 
] 
} 

PUT /my_index/reporting/4 
{ 
    "events": [ 
    { 
     "name": "INSTALL", 
     "date": "2014-11-01" 
    }, 
    { 
     "name": "UNINSTALL", 
     "date": "2014-11-02" 
    }, 
    { 
     "name": "INSTALL", 
     "date": "2014-11-03" 
    } 
] 
} 

PUT /my_index/reporting/5 
{ 
    "events": [ 
    { 
     "name": "INSTALL", 
     "date": "2014-11-01" 
    }, 
    { 
     "name": "UNINSTALL", 
     "date": "2014-11-03" 
    }, 
    { 
     "name": "INSTALL", 
     "date": "2014-11-03" 
    } 
] 
} 

PUT /my_index/reporting/6 
{ 
    "events": [ 
    { 
     "name": "INSTALL", 
     "date": "2014-11-03" 
    }, 
    { 
     "name": "UNINSTALL", 
     "date": "2014-11-03" 
    }, 
    { 
     "name": "INSTALL", 
     "date": "2014-11-05" 
    } 
] 
} 

PUT /my_index/reporting/7 
{ 
    "events": [ 
    { 
     "name": "INSTALL", 
     "date": "2014-11-02" 
    }, 
    { 
     "name": "UNINSTALL", 
     "date": "2014-11-03" 
    }, 
    { 
     "name": "INSTALL", 
     "date": "2014-11-05" 
    } 
] 
} 

PUT /my_index/reporting/8 
{ 
    "events": [ 
    { 
     "name": "INSTALL", 
     "date": "2014-11-01" 
    } 
] 
} 

I хотите получить число тех, кто установил (включая) 2014-11-02 и не удалил (так, UNINSTALL был до 2014-11-02 или не было U NINSTALL) и сгруппировать их в значение date_histogram (чтобы иметь ведро с данными «date» -> «count»).

Мне удалось написать фильтр по этим вложенным данным, поэтому я могу получить этот отфильтрованный результат, но я продолжаю преследовать свой хвост, когда дело доходит до агрегации гистограммы.

Здесь я застрял.

GET /my_index/reporting/_search 
{ 
    "query": { 
    "filtered": { 
     "query": { 
     "match_all": {} 
     }, 
     "filter": { 
     "bool": { 
      "must": [ 
      { 
       "nested": { 
       "path": "events", 
       "filter": { 
        "bool": { 
        "must": [ 
         { 
         "term": { 
          "name": "INSTALL" 
         } 
         }, 
         { 
         "range": { 
          "date": { 
          "gte": "2014-11-02" 
          } 
         } 
         } 
        ] 
        } 
       } 
       } 
      }, 
      { 
       "nested": { 
       "path": "events", 
       "filter": { 
        "bool": { 
        "should": [ 
         { 
         "bool": { 
          "must_not": [ 
          { 
           "term": { 
           "name": "UNINSTALL" 
           } 
          } 
          ] 
         } 
         }, 
         { 
         "bool": { 
          "must": [ 
          { 
           "term": { 
           "name": "UNINSTALL" 
           } 
          }, 
          { 
           "range": { 
           "date": { 
            "lt": "2014-11-02" 
           } 
           } 
          } 
          ] 
         } 
         } 
        ] 
        } 
       } 
       } 
      } 
      ] 
     } 
     } 
    } 
    }, 
    "aggregations": { 
    "filtered_result": { 
     "filter": { 
     "bool": { 
      "must": [ 
      { 
       "nested": { 
       "path": "events", 
       "filter": { 
        "bool": { 
        "must": [ 
         { 
         "term": { 
          "name": "INSTALL" 
         } 
         }, 
         { 
         "range": { 
          "date": { 
          "gte": "2014-11-02" 
          } 
         } 
         } 
        ] 
        } 
       } 
       } 
      }, 
      { 
       "nested": { 
       "path": "events", 
       "filter": { 
        "bool": { 
        "should": [ 
         { 
         "bool": { 
          "must_not": [ 
          { 
           "term": { 
           "name": "UNINSTALL" 
           } 
          } 
          ] 
         } 
         }, 
         { 
         "bool": { 
          "must": [ 
          { 
           "term": { 
           "name": "UNINSTALL" 
           } 
          }, 
          { 
           "range": { 
           "date": { 
            "lt": "2014-11-02" 
           } 
           } 
          } 
          ] 
         } 
         } 
        ] 
        } 
       } 
       } 
      } 
      ] 
     } 
     }, 
     "aggs": { 
     "result": { 
      "nested": { 
      "path": "events" 
      }, 
      "aggs": { 
      "NAME": { 
       "terms": { 
       "field": "events.date", 
       "format": "yyyy-MM-dd", 
       "order": { 
        "_term": "asc" 
       } 
       } 
      } 
      } 
     } 
     } 
    } 
    } 
} 

И мой результат выглядит следующим образом:

... omitted 4 documents that match filter criteria ... 
    "aggregations": { 
     "filtered_result": { 
     "doc_count": 4, <---- this is ok, I really have 4 docs that match criteria 
     "result": { 
      "doc_count": 12, <---- those 4 documents really have 12 events (together) 
      "NAME": { 
       "buckets": [ 
        { 
        "key": 1414800000000, 
        "key_as_string": "2014-11-01", 
        "doc_count": 2 
        }, 
        { 
        "key": 1414886400000, 
        "key_as_string": "2014-11-02", 
        "doc_count": 2 
        }, 
        { 
        "key": 1414972800000, 
        "key_as_string": "2014-11-03", 
        "doc_count": 6 
        }, 
        { 
        "key": 1415145600000, 
        "key_as_string": "2014-11-05", 
        "doc_count": 2 
        } 
       ] 
      } 
     } 
     } 
    } 

И я хотел бы получить что-то вроде:

"buckets": [ 
{ 
    "key_as_string": "2014-11-02", 
    "doc_count": 0 
}, 
{ 
    "key_as_string": "2014-11-03", 
    "doc_count": 2 
}, 
{ 
    "key_as_string": "2014-11-04", 
    "doc_count": 0 
}, 
{ 
    "key_as_string": "2014-11-05", 
    "doc_count": 2 
} 
] 

В основном, 4 документов, которые соответствовали критериям распределены по датам, когда произошел что критерий , 2 документа на «2011-11-03» и два документа на «2014-11-05» (4 документа, которые имеют событие «установить» после 2014-11-02 и после этого не удалили событие (они все еще установлен).

ответ

1

Это частичный ответ.

Там одна главная проблема: в соответствии с вашими данными, существует на самом деле нет документа, который будет соответствовать вашим требованиям, поэтому я добавил:

curl -XPUT 'localhost:9200/my_index/reporting/9' -d '{ 
    "events": [ 
    { 
     "name": "INSTALL", 
     "date": "2014-11-03" 
    } 
] 
}' 

curl -XPUT 'localhost:9200/my_index/reporting/10' -d '{ 
    "events": [ 
    { 
     "name": "INSTALL", 
     "date": "2014-11-03" 
    }, 
    { 
     "name": "UNINSTALL", 
     "date": "2014-11-01" 
    } 
    ] 
}' 

Чтобы иметь возможность применить логику, я изменил схему так что события также включены в родительский элемент - таким образом, вы можете искать «не имеет никаких событий UNINSTALL». Поскольку дело в том, что во вложенном поиске вы всегда смотрите только одно одиночное событие, вы не можете выполнять какие-либо «широкомасштабные» запросы.

curl -XPUT 'localhost:9200/my_index' -d '{ 
    "mappings": { 
    "reporting": { 
     "properties": { 
     "events": { 
      "type": "nested", "include_in_root": true, 
      "properties": { 
      "name": { "type": "string", "index" : "not_analyzed" }, 
      "date": { "type": "date" } 
      } 
     } 
     } 
    } 
    } 
}' 

И теперь к самому запросу. Кажется, что при использовании вложенного фильтра вы не можете перейти непосредственно к «фильтру». Сначала вы должны выполнить «запрос> фильтр> фильтр».

Один совет для написания длинных запросов elasticsearch в целом - помните, что у вас есть «и» и «или» операторы, кроме «must» и «must_not», - это просто написать код в виде кода. В вашем случае:

has_one(event.name == 'INSTALL' && event.date >= '2014-11-02') 
&& has_none(event.name == 'UNINSTALL') 
&& has_none(event.name == 'UNINSTALL' && event.date >= '2014-11-02') 

Или:

has_one(event.name == 'INSTALL' && event.date >= '2014-11-02') 
&& (has_none(event.name == 'UNINSTALL') 
    || has_only(event.name == 'UNINSTALL' && event.date >= '2014-11-02')) 

Я был в состоянии применить все, кроме последнего has_only/has_none. Для этого вы можете попробовать использовать дочерние документы.Там вы можете, по крайней мере, использовать фильтр has_child под must_not bool.

Текущий запрос:

GET /my_index/reporting/_search 
{ 
    "query": { 
    "filtered": { 
     "query": { 
     "match_all": {} 
     }, 
     "filter": { 
     "and": { 
      "filters": [ 
      { 
       "or": { 
       "filters": [ 
        { 
        "bool": { 
         "must_not": [ 
         { 
          "term": { 
          "events.name": "UNINSTALL" 
          } 
         } 
         ] 
        } 
        }, 
        { 
        "nested": { 
         "path": "events", 
         "query": { 
         "filtered": { 
          "filter": { 
          "bool": { 
           "must": [ 
           { 
            "term": { 
            "name": "UNINSTALL" 
            } 
           }, 
           { 
            "range": { 
            "date": { 
             "lt": "2014-11-02" 
            } 
            } 
           } 
           ] 
          } 
          } 
         } 
         } 
        } 
        } 
       ] 
       } 
      }, 
      { 
       "nested": { 
       "path": "events", 
       "query": { 
        "filtered": { 
        "filter": { 
         "bool": { 
         "must": [ 
          { 
          "term": { 
           "name": "INSTALL" 
          } 
          }, 
          { 
          "range": { 
           "date": { 
           "gte": "2014-11-02" 
           } 
          } 
          } 
         ] 
         } 
        } 
        } 
       } 
       } 
      } 
      ] 
     } 
     } 
    } 
    }, 
    "aggregations": { 
    "filtered_result": { 
     "filter": { 
     "and": { 
      "filters": [ 
      { 
       "or": { 
       "filters": [ 
        { 
        "bool": { 
         "must_not": [ 
         { 
          "term": { 
          "events.name": "UNINSTALL" 
          } 
         } 
         ] 
        } 
        }, 
        { 
        "nested": { 
         "path": "events", 
         "query": { 
         "filtered": { 
          "filter": { 
          "bool": { 
           "must": [ 
           { 
            "term": { 
            "name": "UNINSTALL" 
            } 
           }, 
           { 
            "range": { 
            "date": { 
             "lt": "2014-11-02" 
            } 
            } 
           } 
           ] 
          } 
          } 
         } 
         } 
        } 
        } 
       ] 
       } 
      }, 
      { 
       "nested": { 
       "path": "events", 
       "query": { 
        "filtered": { 
        "filter": { 
         "bool": { 
         "must": [ 
          { 
          "term": { 
           "name": "INSTALL" 
          } 
          }, 
          { 
          "range": { 
           "date": { 
           "gte": "2014-11-02" 
           } 
          } 
          } 
         ] 
         } 
        } 
        } 
       } 
       } 
      } 
      ] 
     } 
     }, 
     "aggs": { 
     "result": { 
      "nested": { 
      "path": "events" 
      }, 
      "aggs": { 
      "NAME": { 
       "terms": { 
       "field": "date", 
       "format": "yyyy-MM-dd", 
       "order": { 
        "_term": "asc" 
       } 
       } 
      } 
      } 
     } 
     } 
    } 
    } 
} 
Смежные вопросы