2015-06-09 10 views
32

Ich versuche, verwandte Tags zu der aktuell angezeigten zu finden. Jedes Dokument in unserem Index ist markiert. Jeder Tag besteht aus zwei Teilen - einen ID und Textname:So erhalten Sie eine Elasticsearch-Aggregation mit mehreren Feldern

{ 
    ... 
    meta: { 
     ... 
     tags: [ 
      { 
       id: 123, 
       name: 'Biscuits' 
      }, 
      { 
       id: 456, 
       name: 'Cakes' 
      }, 
      { 
       id: 789, 
       name: 'Breads' 
      } 
     ] 
    } 
} 

holt die verwandten Tags bin ich einfach die Dokumente abfragen und ein Aggregat von ihrem Tags erhalten:

{ 
    "query": { 
     "bool": { 
      "must": [ 
       { 
        "match": { 
         "item.meta.tags.id": "123" 
        } 
       }, 
       { 
        ... 
       } 
      ] 
     } 
    }, 
    "aggs": { 
     "baked_goods": { 
      "terms": { 
       "field": "item.meta.tags.id", 
       "min_doc_count": 2 
      } 
     } 
    } 
} 

Das funktioniert perfekt Ich bekomme die Ergebnisse, die ich möchte. Allerdings benötige ich sowohl die Tag-ID als auch den Namen, um etwas Nützliches zu tun. Ich habe untersucht, wie dies zu erreichen, scheinen die Lösungen zu sein:

  1. die Felder kombinieren, wenn
  2. Ein Skript Indizierung der Felder
  3. Eine verschachtelte Aggregation

Option ein bis munge zusammen und Zwei sind nicht verfügbar für mich, also habe ich mit 3, aber es reagiert nicht in der erwarteten Weise. Given (noch auf der Suche nach Dokumenten auch mit ‚Biscuits‘ markiert) die folgenden Abfrage:

{ 
    ... 
    "aggs": { 
     "baked_goods": { 
      "terms": { 
       "field": "item.meta.tags.id", 
       "min_doc_count": 2 
      }, 
      "aggs": { 
       "name": { 
        "terms": { 
         "field": "item.meta.tags.name" 
        } 
       } 
      } 
     } 
    } 
} 

ich dieses Ergebnis erhalten:

{ 
    ... 
    "aggregations": { 
     "baked_goods": { 
      "buckets": [ 
       { 
        "key": "456", 
        "doc_count": 11, 
        "name": { 
         "buckets": [ 
          { 
           "key": "Biscuits", 
           "doc_count": 11 
          }, 
          { 
           "key": "Cakes", 
           "doc_count": 11 
          } 
         ] 
        } 
       } 
      ] 
     } 
    } 
} 

Die verschachtelte Aggregation umfasst sowohl den Suchbegriff und den Tag Ich bin nach (in alphabetischer Reihenfolge).

Ich habe versucht, dies zu mildern, indem Sie eine exclude der verschachtelten Aggregation hinzufügen, aber dies verlangsamte die Abfrage viel zu viel (etwa 100 mal für 500000 Dokumente). Bisher ist die schnellste Lösung, das Ergebnis manuell zu entfernen.

Was ist der beste Weg, um eine Zusammenfassung von Tags mit der Tag-ID und dem Tag-Namen in der Antwort zu erhalten?

Danke, dass Sie es bis hierher geschafft haben!

Antwort

44

Ihr Aussehen tags ist nicht nested. Für diese Aggregation zu arbeiten, you need it nested, so dass es eine Verbindung zwischen einem id und einem name gibt. Ohne nested die Liste der id s ist nur ein Array und die Liste der name s ist ein weiteres Array:

"item": { 
     "properties": { 
     "meta": { 
      "properties": { 
      "tags": { 
       "type": "nested",   <-- nested field 
       "include_in_parent": true, <-- to, also, keep the flat array-like structure 
       "properties": { 
       "id": { 
        "type": "integer" 
       }, 
       "name": { 
        "type": "string" 
       } 
       } 
      } 
      } 
     } 
     } 
    } 

Beachten Sie auch, dass ich auf die Abbildung dieser Linie "include_in_parent": true hinzugefügt haben, was bedeutet, dass Ihre nested-Tags, verhalten Sie sich auch wie eine "flache" Array-ähnliche Struktur.

Also alles, was Sie bisher in Ihren Abfragen hatten, funktioniert immer noch ohne Änderungen an den Abfragen.

{ 
    "aggs": { 
    "baked_goods": { 
     "nested": { 
     "path": "item.meta.tags" 
     }, 
     "aggs": { 
     "name": { 
      "terms": { 
      "field": "item.meta.tags.id" 
      }, 
      "aggs": { 
      "name": { 
       "terms": { 
       "field": "item.meta.tags.name" 
       } 
      } 
      } 
     } 
     } 
    } 
    } 
} 

Und das Ergebnis ist wie folgt:

Aber für diese Abfrage von Ihnen, die Aggregation zu so etwas ändern muss

"aggregations": { 
     "baked_goods": { 
     "doc_count": 9, 
     "name": { 
      "doc_count_error_upper_bound": 0, 
      "sum_other_doc_count": 0, 
      "buckets": [ 
       { 
        "key": 123, 
        "doc_count": 3, 
        "name": { 
        "doc_count_error_upper_bound": 0, 
        "sum_other_doc_count": 0, 
        "buckets": [ 
         { 
          "key": "biscuits", 
          "doc_count": 3 
         } 
        ] 
        } 
       }, 
       { 
        "key": 456, 
        "doc_count": 2, 
        "name": { 
        "doc_count_error_upper_bound": 0, 
        "sum_other_doc_count": 0, 
        "buckets": [ 
         { 
          "key": "cakes", 
          "doc_count": 2 
         } 
        ] 
        } 
       }, 
       ..... 
+1

@i_like_robots Ich bin neugierig, Hast du meine vorgeschlagene Lösung getestet? –

+1

er entschied sich, das Kopfgeld für sich selbst zu behalten, danke für die gute Antwort! – asktomsk

+2

Am Ende, ja! Wir konnten schließlich die Zeit damit verbringen, einen neuen Index mit richtig verschachtelten Feldern zu erstellen, aber ich fürchte, es war erst vor kurzem. Vielen Dank für deine Zeit, meine Frage zu beantworten und ich entschuldige mich dafür, dass ich die Stack Overflow-Etikette vernachlässige! –

Verwandte Themen