2015-09-05 7 views
6

Ich bin nur ein paar Tage neu in ElasticSearch, und als Lernübung einen rudimentären Job-Scraper implementiert, der Jobs von einigen Job-Listing-Sites aggregiert und einen Index mit einigen Daten füllt mit mir zu spielen.Aggregation auf gefiltert, verschachtelte Inner_Hits Abfrage in ElasticSearch

Mein Index enthält ein Dokument für jede Website, das Jobs auflistet. Eine Eigenschaft jedes dieser Dokumente ist ein 'jobs'-Array, das ein Objekt für jeden Job enthält, der auf dieser Site existiert. Ich überlege, jeden Job als eigenes Dokument zu indizieren (vor allem, da die ElasticSearch-Dokumentation sagt, dass inner_hits ein experimentelles Feature ist), aber im Moment versuche ich herauszufinden, ob ich mit den inner_hits und verschachtelten Features von ElasticSearch das erreichen kann, was ich möchte .

Ich kann nur übereinstimmende Jobs abfragen, filtern und zurückgeben. Ich bin mir jedoch nicht sicher, wie man die gleichen inner_hits-Bedingungen auf eine Aggregation anwendet.

Das ist mein Mapping:

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

Dies ist eine Abfrage und Aggregat, das ich (von Node.js) versuchen:

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); 
}); 

Das gibt mir wieder all inner_hits von Jobs in New York, aber das Aggregat zeigt mir, dass es für jeden Standort und jede Firma zählt, nicht nur für diejenigen, die zu den inner_hits passen.

Haben Sie Vorschläge, wie Sie nur die Daten in den passenden inner_hits zusammenfassen?

Edit: Ich aktualisiere dies, um einen Export der Mapping-und Indexdaten, wie angefordert. Ich exportierte dieses elasticdump Tool mit Taskrabbit, finden Sie hier: https://github.com/taskrabbit/elasticsearch-dump

Der Index: http://pastebin.com/WaZwBwn4 Die Abbildung: http://pastebin.com/ZkGnYN94

Die oben verknüpften Daten, dass aus dem Beispielcode in meiner ursprünglichen Frage unterscheidet sich der Index mit dem Namen jobsites6 ist in den Daten statt JobsitesIdx wie in der Frage bezeichnet. Der Typ in den Daten ist "Job", während im obigen Code "Sites" sind.

Ich habe den Rückruf im obigen Code ausgefüllt, um die Antwortdaten anzuzeigen. Ich sehe nur Jobs in New York von der foreach-Schleife der inner_hits, wie erwartet, aber ich diese Aggregation für die Lage bin zu sehen:

[ { 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 } ] 

Da mein inner_hits die in New York beschränkt ist, kann ich sehen, dass Die Aggregation ist nicht auf meinem inneren_Hits, weil es mir zählt für alle Standorte.

+0

Können Sie einige Beispieldaten angeben (vielleicht in einem Sinn oder etwas)? Und die Ergebnisse, die Sie erwarten, zurückgegeben werden? –

Antwort

10

Sie können dies erreichen, indem Sie denselben Filter in Ihrer Aggregation hinzufügen, um nur New York-Jobs einzubeziehen. Beachten Sie auch, dass Sie in Ihrer zweiten Aggregation company.raw hatten, aber das jobs.company Feld in Ihrer Zuordnung keinen not_analyzed Teil mit dem Namen raw hat. Sie müssen es wahrscheinlich hinzufügen, wenn Sie den nicht analysierten Firmennamen aggregieren möchten.

{ 
    "_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

Ich habe bestätigt, dass dies funktioniert, danke!Wie ich es verstehe, wirken sich die über "query" zurückgegebenen übergeordneten Dokumente auf den Umfang der Aggregation aus; Es wäre schön, wenn ES das gleiche zu inner_hits anwenden würde, ohne die Beschränkungen des Filters in den aggs wiederholen zu müssen. Auf der anderen Seite, vielleicht die Verwendung der 'experimental' inner_hits Feature ist für Ärger. Außerdem hatte ich eine Notiz an mich, jobs.company.raw hinzuzufügen, wenn ich das nächste Mal den Index neu erstellte, guter Haken. – mmccaff

Verwandte Themen