2015-06-09 25 views
32

Próbuję znaleźć powiązane tagi z aktualnie wyświetlanym. Każdy dokument w naszym indeksie jest oznaczony tagami. Każdy znacznik jest utworzony z dwóch części - ID i tekstową nazwę:Jak uzyskać agregację Elasticsearch z wieloma polami

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

Aby pobrać related tags Ja po prostu zapytań dokumentów i uzyskiwanie kruszywa ich tagami:

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

To działa doskonale , Dostaję wyniki, które chcę. Wymagam jednak nazwy znacznika ID i, aby zrobić coś użytecznego. I zbadali, jak osiągnąć ten cel, rozwiązania wydają się być:

  1. Połącz pól podczas indeksowania
  2. skrypt munge razem pól
  3. Zagnieżdżona agregacja

Opcja pierwsza i dwa są niedostępne dla mnie, więc chodziłem z 3, ale nie reagowałem w oczekiwany sposób. Biorąc pod uwagę następujące zapytanie (wciąż szukając dokumentów również z tagami suchary "):

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

dostanę ten wynik:

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

Agregacja zagnieżdżona obejmuje zarówno wyszukiwane hasło i tagu Jestem po (w kolejności alfabetycznej).

Próbowałem złagodzić tę sytuację, dodając exclude do zagnieżdżonej agregacji, ale spowolniło to znacznie zbyt mocno (około 100 razy dla 500000 dokumentów). Jak dotąd najszybszym rozwiązaniem jest ręczne usunięcie wyniku.

Jaki jest najlepszy sposób uzyskania agregacji tagów z identyfikatorem tagu i nazwą znacznika w odpowiedzi?

Dzięki za dotarcie tak daleko!

Odpowiedz

44

Wygląda na to, że Twój tags nie jest . Aby agregacja działała, you need it nested, tak aby istniało powiązanie między id i name. Bez nested lista id s jest tylko tablicą i lista name s jest inna tablica:

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

Należy również pamiętać, że dodałem do mapowania ta linia "include_in_parent": true co oznacza, że ​​nested tagi, także zachowują się jak "płaska" struktura podobna do tablicy.

Wszystko, co do tej pory zawierałeś w swoich zapytaniach, będzie działało bez żadnych zmian w zapytaniach.

Ale dla tego konkretnego zapytania od Ciebie, agregacja musi się zmienić na coś takiego:

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

a wynik jest taki:

"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 Jestem ciekaw, przetestowałeś moje sugerowane rozwiązanie? –

+1

postanowił zachować nagrodę za siebie, dziękuję za dobrą odpowiedź! – asktomsk

+2

W końcu tak! W końcu udało nam się poświęcić czas na stworzenie nowego indeksu z prawidłowo zagnieżdżonymi polami, ale obawiam się, że dopiero niedawno. Dziękuję za rozmowę na moje pytanie i przepraszam za zaniedbanie jakiejkolwiek etykiety Stack Overflow! –