2016-08-01 43 views
0

Ich habe folgendes Objekt, deren value Attribut ist ein verschachtelter Objekt-Typ:Wie kann eine Elasticsearch-Aggregation mit einem Term und einer Summe auf verschiedenen verschachtelten Objekten abgefragt werden?

{ 
    "metadata": { 
     "tenant": "home", 
     "timestamp": "2016-03-24T23:59:38Z" 
    }, 
    "value": { 
     { "key": "foo", "int_value": 100 }, 
     { "key": "bar", "str_value": "taco" } 
    } 
} 

dieser Objekttyp die folgende Zuordnung hat:

{ 
    "my_index": { 
     "mappings": { 
      "my_doctype": { 
       "properties": { 
        "metadata": { 
         "properties": { 
          "tenant": { 
           "type": "string", 
           "index": "not_analyzed" 
          }, 
          "timestamp": { 
           "type": "date", 
           "format": "dateOptionalTime" 
          } 
         } 
        }, 
        "value": { 
         "type": "nested", 
         "properties": { 
          "str_value": { 
           "type": "string", 
           "index": "not_analyzed" 
          }, 
          "int_value": { 
           "type": "long" 
          }, 
          "key": { 
           "type": "string", 
           "index": "not_analyzed" 
          } 
         } 
        } 
       } 
      } 
     } 
    } 
} 

Mit diesem Aufbau würde Ich mag eine Aggregation durchzuführen, dass führt zu folgendem Ergebnis:

  • Führen Sie eine term Aggregation auf der str_value Attribut von Objekten in dem die key-"bar"
  • In jedem Eimer aus der obigen Aggregation erstellt eingestellt ist, die Berechnung der sum der int_value Attribute in dem die key zu "foo" gesetzt
  • Die Ergebnisse wurden in einer date_histogram für eine angelegte gegebener Zeitbereich.

Mit diesem Ziel vor Augen, ich in der Lage gewesen, die term und date_histogram Aggregationen bekommen auf meine verschachtelten Objekten zu arbeiten, haben aber kein Glück Durchführung der zweiten Ebene der Berechnung hatte. Hier ist die aktuelle Abfrage ich versucht bin zu Arbeits erhalten:

{ 
    "query": { 
    "match_all": {} 
    }, 
    "aggs": { 
    "filters": { 
     "filter": { 
     "bool": { 
      "must": [ 
      { 
       "term": { 
       "metadata.org": "gw" 
       } 
      }, 
      { 
       "range": { 
       "metadata.timestamp": { 
        "gte": "2016-03-24T00:00:00.000Z", 
        "lte": "2016-03-24T23:59:59.999Z" 
       } 
       } 
      } 
      ] 
     } 
     }, 
     "aggs": { 
     "intervals": { 
      "date_histogram": { 
      "field": "metadata.timestamp", 
      "interval": "1d", 
      "min_doc_count": 0, 
      "extended_bounds": { 
       "min": "2016-03-24T00:00:00Z", 
       "max": "2016-03-24T23:59:59Z" 
      }, 
      "format": "yyyy-MM-dd'T'HH:mm:ss'Z'" 
      }, 
      "aggs": { 
      "nested_type": { 
       "nested": { 
       "path": "value" 
       }, 
       "aggs": { 
       "key_filter": { 
        "filter": { 
        "term": { 
         "value.key": "bar" 
        } 
        }, 
        "aggs": { 
        "groupBy": { 
         "terms": { 
         "field": "value.str_value" 
         }, 
         "aggs": { 
         "other_nested": { 
          "reverse_nested": { 
          "path": "value" 
          }, 
          "aggs": { 
          "key_filter": { 
           "filter": { 
           "term": { 
            "value.key": "foo" 
           } 
           }, 
           "aggs": { 
           "amount_sum": { 
            "sum": { 
            "field": "value.int_value" 
            } 
           } 
           } 
          } 
          } 
         } 
         } 
        } 
        } 
       } 
       } 
      } 
      } 
     } 
     } 
    } 
    } 
} 

Das Ergebnis, das ich erwarten bin erhalten von Elasticsearch aussehen würde wie folgt aus:

{ 
    "took": 1, 
    "timed_out": false, 
    "_shards": { 
    "total": 5, 
    "successful": 5, 
    "failed": 0 
    }, 
    "hits": { 
    "total": 7, 
    "max_score": 0.0, 
    "hits": [] 
    }, 
    "aggregations": { 
    "filters": { 
     "doc_count": 2, 
     "intervals": { 
     "buckets": [ 
      { 
      "key_as_string": "2016-03-24T00:00:00Z", 
      "key": 1458777600000, 
      "doc_count": 2, 
      "nested_type": { 
       "doc_count": 5, 
       "key_filter": { 
       "doc_count": 2, 
       "groupBy": { 
        "doc_count_error_upper_bound": 0, 
        "sum_other_doc_count": 0, 
        "buckets": [ 
        { 
         "key": "taco", 
         "doc_count": 1, 
         "other_nested": { 
         "doc_count": 1, 
         "key_filter": { 
          "doc_count": 1, 
          "amount_sum": { 
          "value": 100.0 
          } 
         } 
         } 
        } 
        ] 
       } 
       } 
      } 
      } 
     ] 
     } 
    } 
    } 
} 

jedoch die innerste Objekt (...groupBy.buckets.key_filter.amount_sum) hat seine value Rückkehr 0.0 anstelle von 100.0.

Ich denke, dies liegt an der Tatsache, dass verschachtelte Objekte als separate Dokumente indiziert werden, so dass die Filterung durch einen Wert key Attribut ermöglicht es mir nicht, gegen einen anderen key abzufragen.

Müßte jemand eine Idee, wie man diese Art der Abfrage an der Arbeit?

Für ein bisschen mehr Kontext ist der Grund für diese Dokumentstruktur, weil ich mit unterschiedlichen Werten in Konflikt stehenden Schlüsselnamen nicht den Inhalt der JSON-Dokumente steuern, die indiziert werden, können so unterschiedliche tenant s (zB {"tenant": "abc", "value": {"foo": "a"} } vs. {"tenant": "xyz", "value": {"foo": 1} } . das Verfahren I ist die von diesen Elasticsearch Blog Post angelegt zu verwenden versuchen, wo es Objekte zu verwandeln empfiehlt, die Sie verschachtelte Objekte tun nicht in eine Struktur steuern und zu verwenden, um mit diesem (speziell dem Nested fields for each data type Abschnitt zu helfen, der Artikel). würde ich auch offen sein für eine bessere Art und Weise zu lernen, diese Situation nicht Steuerung des Dokuments JSON Struktur zu behandeln, wenn es einen gibt, so dass ich Aggregationen durchführen kann.

Vielen Dank!

EDIT: Ich bin mit Elasticsearch 1.5.

Antwort