2016-01-18 9 views
5

Bitte helfen Sie mir einen Mechanismus zu finden, um über die folgende Domäne zu aggregieren oder zu beweisen, dass es in der aktuellen API nicht existiert.Verknüpfung von reverse_nested-Aggregationen in Elasticsearch

curl -XDELETE 127.0.0.1:9200/test_index 

    curl -XPUT 127.0.0.1:9200/test_index -d '{ 
     "mappings": { 
      "contact": { 
       "properties": { 
        "facebook_profile": { 
         "type": "nested", 
         "properties": { 
          "education": { 
           "type": "string" 
          }, 
          "year": { 
           "type": "integer" 
          } 
         } 
        }, 
        "google_profile": { 
         "type": "nested", 
         "properties": { 
          "education": { 
           "type": "string" 
          }, 
          "year": { 
           "type": "integer" 
          } 
         } 
        } 
       } 
      } 
     } 
    }' 

    curl -XPUT 127.0.0.1:9200/test_index/contact/contact1 -d '{ 
     "google_profile": { 
      "education": "stanford", "year": 1990 
     } 
    }' 

    curl -XPUT 127.0.0.1:9200/test_index/contact/contact2 -d ' 
    { 
     "facebook_profile": { 
      "education": "stanford", "year": 1990 
     } 
    }' 

Wie kann man ES abfragen, um Statistiken darüber zu erhalten, wie viele Kontakte von bestimmten Universitäten absolviert wurden?

fand ich eine Möglichkeit, aber es gibt mir nicht gewünschte Ergebnis, da es nicht auf die oben gestellte Frage in Bezug auf Kontakte beantworten, sondern nur auf ihre speziellen Profile (verschachtelte docs):

curl -XPOST '127.0.0.1:9200/test_index/_search?search_type=count&pretty=true' -d '{ 
     "aggs": { 
      "facebook_educations": { 
       "aggs": { 
        "field": { 
         "terms": { 
          "field": "contact.facebook_profile.education" 
         }, 
         "aggs": { 
          "reverse": { 
           "reverse_nested": { 
           } 
          } 
         } 
        } 
       }, 
       "nested": { 
        "path": "contact.facebook_profile" 
       } 
      }, 
      "google_educations": { 
       "aggs": { 
        "field": { 
         "terms": { 
          "field": "contact.google_profile.education" 
         }, 
         "aggs": { 
          "reverse": { 
           "reverse_nested": { 
           } 
          } 
         } 
        } 
       }, 
       "nested": { 
        "path": "contact.google_profile" 
       } 
      } 
     } 
    }' 

Was gibt mir:

"aggregations" : { 
     "facebook_educations" : { 
      "doc_count" : 1, 
      "field" : { 
      "doc_count_error_upper_bound" : 0, 
      "sum_other_doc_count" : 0, 
      "buckets" : [ { 
       "key" : "stanford", 
       "doc_count" : 1, 
       "reverse" : { 
       "doc_count" : 1 
       } 
      } ] 
      } 
     }, 
     "google_educations" : { 
      "doc_count" : 1, 
      "field" : { 
      "doc_count_error_upper_bound" : 0, 
      "sum_other_doc_count" : 0, 
      "buckets" : [ { 
       "key" : "stanford", 
       "doc_count" : 1, 
       "reverse" : { 
       "doc_count" : 1 
       } 
      } ] 
      } 
     } 
    } 

Aber hier kann ich nicht sicher sein, wenn man gefunden Kontakt gleich oder verschieden doc (parent) ist bzw. kann ich nicht auf meine erste Frage beantworten.

Vielen Dank für einen Hinweis.

Antwort

0

Es klingt, als ob Sie versuchen, aggregate on multiple fields. Dies wird in Elasticsearch nicht direkt unterstützt, aber es gibt Möglichkeiten, dies zu umgehen und die gewünschten Ergebnisse zu erhalten.

Werfen Sie einen Blick auf die discussion on Github, und auch in der documentation.

Wenn ich richtig verstehe, ob "Stanford" in facebook_profile.education oder google_profile.education erscheint, möchten Sie die contact nur einmal in der Aggregation gezählt werden.

Sie sollten in der Lage sein, dies auf zwei Arten in einem tun:

  1. ein Skript verwenden, um die Werte in den Feldern gespeichert verketten:

    { 
        "aggs": { 
        "by_education": { 
         "terms": { 
         "script": "doc['contact.facebook_profile.education'].values + doc['contact.google_profile.education'].values" 
         } 
        } 
        } 
    } 
    
  2. Sie erstellen eine neue erstellen dediziertes Feld zur Indexzeit, das die Werte aus beiden Feldern enthält, mit der Option copy_to. Dann aggregiere auf dem einzelnen Feld. Beispielsweise könnten Sie den Inhalt beider Felder in ein neues Feld namens education_combined kopieren.

    { 
        "mappings":{ 
        "contact":{ 
         "properties":{ 
         "facebook_profile":{ 
          "type":"nested", 
          "properties":{ 
          "education":{ 
           "type":"string", 
           "copy_to":"education_combined" 
          }, 
          "year":{ 
           "type":"integer" 
          } 
          } 
         }, 
         "google_profile":{ 
          "type":"nested", 
          "properties":{ 
          "education":{ 
           "type":"string", 
           "copy_to":"education_combined" 
          }, 
          "year":{ 
           "type":"integer" 
          } 
          } 
         }, 
         "education_combined":{ 
          "type":"string" 
         } 
         } 
        } 
        } 
    } 
    

    Dann aggregieren einfach auf education_combined:

    { 
        "aggs": { 
        "by_education": { 
         "terms": { "field": "education_combined" } 
        } 
        } 
    } 
    
+0

Ihr erster Vorschlag einfach nicht funktioniert, weil für verschachtelte Dokumente müssen Sie _Source Feld zugreifen. Die zweite Option mag funktionieren, aber leider nicht in meinem Fall, da ich Dokumente verschachtelt habe, die in untergeordnete Dokumente eingebettet sind, und ich versuche, eine Art has_parent-Aggregation durchzuführen. Dies ist, was ich für jetzt http://stackoverflow.com/questions/35061945/match-query-inside-script-elasticsearch habe. Trotzdem danke – Serj