2015-09-05 11 views
6

Mam tylko kilka dni nowości w ElasticSearch, a jako ćwiczenie edukacyjne wprowadzono elementarną skrobak do pracy, który agreguje zadania z kilku witryn z ofertami pracy i wypełnia indeks niektórymi danymi dla mnie do zabawy.Agregacja na przefiltrowanym, zagnieżdżonym zapytaniu inner_hits w ElasticSearch

Mój indeks zawiera dokument dla każdej witryny z listą zadań. Właściwością każdego z tych dokumentów jest tablica "jobs", która zawiera obiekt dla każdego zadania istniejącego w tej witrynie. Rozważam indeksowanie każdego zadania jako własnego dokumentu (zwłaszcza, że ​​dokumentacja ElasticSearch mówi, że inner_hits jest funkcją eksperymentalną), ale na razie próbuję sprawdzić, czy mogę osiągnąć to, co chcę zrobić, używając inner_hits i zagnieżdżonych funkcji ElasticSearch .

Jestem w stanie przesyłać zapytania, filtrować i zwracać tylko pasujące zadania. Jednak nie jestem pewien, jak zastosować te same ograniczenia inner_hits do agregacji.

To mój mapowania:

{ 
    "jobsitesIdx" : { 
    "mappings" : { 
     "sites" : { 
     "properties" : { 
      "createdAt" : { 
      "type" : "date", 
      "format" : "dateOptionalTime" 
      }, 
      "jobs" : { 
      "type" : "nested", 
      "properties" : { 
       "company" : { 
       "type" : "string" 
       }, 
       "engagement" : { 
       "type" : "string" 
       }, 
       "link" : { 
       "type" : "string", 
       "index" : "not_analyzed" 
       }, 
       "location" : { 
       "type" : "string", 
       "fields" : { 
        "raw" : { 
        "type" : "string", 
        "index" : "not_analyzed" 
        } 
       } 
       }, 
       "title" : { 
       "type" : "string" 
       } 
      } 
      }, 
      "jobscount" : { 
      "type" : "long" 
      }, 
      "sitename" : { 
      "type" : "string" 
      }, 
      "url" : { 
      "type" : "string" 
      } 
     } 
     } 
    } 
    } 
} 

To zapytanie i kruszywo, które usiłuję (od node.js):

client.search({ 
    "index": 'jobsitesIdx, 
    "type": 'sites', 
    "body": { 


    "aggs" : { 
      "jobs" : { 
       "nested" : { 
        "path" : "jobs" 
       }, 
       "aggs" : { 
        "location" : { "terms" : { "field" : "jobs.location.raw", "size": 25 } }, 
        "company" : { "terms" : { "field" : "jobs.company.raw", "size": 25 } } 
       } 
      } 
     }, 


    "query": { 
     "filtered": { 
      "query": {"match_all": {}}, 
      "filter": { 
      "nested": { 
       "inner_hits" : { "size": 1000 }, 
       "path": "jobs", 
       "query":{ 
       "filtered": { 
        "query": { "match_all": {}}, 
        "filter": { 
        "and": [ 
         {"term": {"jobs.location": "york"}}, 
         {"term": {"jobs.location": "new"}} 
        ] 
        } 
       } 
       } 
      } 
      } 
     } 
     } 
    } 
}, function (error, response) { 
    response.hits.hits.forEach(function(jobsite) { 
    jobs = jobsite.inner_hits.jobs.hits.hits; 

    jobs.forEach(function(job) { 
     console.log(job); 
    }); 

}); 

    console.log(response.aggregations.jobs.location.buckets); 
}); 

Daje mi wszystkie inner_hits miejsc pracy w Nowej York, ale agregat pokazuje mi, jak liczę dla każdej lokalizacji i firmy, nie tylko te pasujące do inner_hits.

Jakieś sugestie, jak uzyskać agregat tylko na danych zawartych w pasujących inner_hits?

Edytuj: Aktualizuję to, aby uwzględnić eksport danych mapowania i indeksów, zgodnie z żądaniem. I eksportowane ten przyrządem elasticdump Taskrabbit za, znaleźć tutaj: https://github.com/taskrabbit/elasticsearch-dump

indeksie: http://pastebin.com/WaZwBwn4 Odwzorowanie: http://pastebin.com/ZkGnYN94

Powyższy związana danych różni się od przykładowego kodu w moim oryginalne pytanie, że indeks jest o nazwie jobsites6 w danych zamiast jobsitesIdx, o których mowa w pytaniu. Ponadto typem danych jest "zadanie", podczas gdy w powyższym kodzie jest to "witryna".

Wypełniłem wywołanie zwrotne w powyższym kodzie, aby wyświetlić dane odpowiedzi. Widzę tylko pracy w Nowym Jorku z pętli foreach z inner_hits, zgodnie z oczekiwaniami, jednak widzę to agregacji dla lokalizacji:

[ { key: 'New York, NY', doc_count: 243 }, 
    { key: 'San Francisco, CA', doc_count: 92 }, 
    { key: 'Chicago, IL', doc_count: 43 }, 
    { key: 'Boston, MA', doc_count: 39 }, 
    { key: 'Berlin, Germany', doc_count: 22 }, 
    { key: 'Seattle, WA', doc_count: 22 }, 
    { key: 'Los Angeles, CA', doc_count: 20 }, 
    { key: 'Austin, TX', doc_count: 18 }, 
    { key: 'Anywhere', doc_count: 16 }, 
    { key: 'Cupertino, CA', doc_count: 15 }, 
    { key: 'Washington D.C.', doc_count: 14 }, 
    { key: 'United States', doc_count: 11 }, 
    { key: 'Atlanta, GA', doc_count: 10 }, 
    { key: 'London, UK', doc_count: 10 }, 
    { key: 'Ulm, Deutschland', doc_count: 10 }, 
    { key: 'Riverton, UT', doc_count: 9 }, 
    { key: 'San Diego, CA', doc_count: 9 }, 
    { key: 'Charlotte, NC', doc_count: 8 }, 
    { key: 'Irvine, CA', doc_count: 8 }, 
    { key: 'London', doc_count: 8 }, 
    { key: 'San Mateo, CA', doc_count: 8 }, 
    { key: 'Boulder, CO', doc_count: 7 }, 
    { key: 'Houston, TX', doc_count: 7 }, 
    { key: 'Palo Alto, CA', doc_count: 7 }, 
    { key: 'Sydney, Australia', doc_count: 7 } ] 

Ponieważ moje inner_hits są ograniczone do tych w Nowym Jorku, widzę, że agregacja nie znajduje się na moich wewnętrznych funkcjach, ponieważ daje mi to policzenie dla wszystkich lokalizacji.

+0

Czy możesz podać przykładowe dane (może w istocie rzeczy)? A wyniki, które spodziewają się, że zostaną zwrócone? –

Odpowiedz

10

Możesz to osiągnąć, dodając ten sam filtr w swojej agregacji, by uwzględniać tylko oferty z Nowego Jorku. Należy również zauważyć, że w drugiej agregacji masz company.raw, ale w twoim mapowaniu pole jobs.company nie ma części o nazwie not_analyzed o nazwie raw, więc prawdopodobnie musisz ją dodać, jeśli chcesz zagregować na nierozpoznanej nazwie firmy.

{ 
    "_source": [ 
    "sitename" 
    ], 
    "query": { 
    "filtered": { 
     "filter": { 
     "nested": { 
      "inner_hits": { 
      "size": 1000 
      }, 
      "path": "jobs", 
      "query": { 
      "filtered": { 
       "filter": { 
       "terms": { 
        "jobs.location": [ 
        "new", 
        "york" 
        ] 
       } 
       } 
      } 
      } 
     } 
     } 
    } 
    }, 
    "aggs": { 
    "jobs": { 
     "nested": { 
     "path": "jobs" 
     }, 
     "aggs": { 
     "only_loc": { 
      "filter": {   <----- add this filter 
      "terms": { 
       "jobs.location": [ 
       "new", 
       "york" 
       ] 
      } 
      }, 
      "aggs": { 
      "location": { 
       "terms": { 
       "field": "jobs.location.raw", 
       "size": 25 
       } 
      }, 
      "company": { 
       "terms": { 
       "field": "jobs.company", 
       "size": 25 
       } 
      } 
      } 
     } 
     } 
    } 
    } 
} 
+0

Potwierdziłem, że to działa, dziękuję!Jak rozumiem, dokumenty nadrzędne zwracane przez "zapytanie" wpływają na zakres agregacji; byłoby miło, gdyby ES zezwolił na to samo w odniesieniu do inner_hits bez konieczności powtarzania ograniczeń filtru ponownie w aggs. Z drugiej strony, być może użycie "eksperymentalnej" funkcji inner_hits powoduje kłopoty. Miałem również notatkę dla siebie, aby dodać jobs.company.raw następnym razem, gdy odtworzyłem indeks, dobry połów. – mmccaff