2016-04-27 13 views
0

Ich habe eine Elasticsearch Datenbank der Bücher:Elasticsearch - Aggregation von einzigartigen zählt

{ 
    "id": 1, 
    "name": "Animal Farm" 
}, 
{ 
    "id": 2, 
    "name": "Brave New World" 
}, 
{ 
    "id": 3, 
    "name": "Nineteen Eighty-Four" 
}, 
{ 
    "id": 4, 
    "name": "Animal Farm" 
}, 
{ 
    "id": 5, 
    "name": "We" 
} 

Wie Sie sehen können, die Bücher mit id von 1 und 4 den Konflikt Buchname „Animal Farm“ haben. Sie sind jedoch verschiedene Bücher. Einer ist von George Orwell, und ein anderer ist buchstäblich über Nutztiere.

Ich möchte wissen, wie oft die Buchnamen widersprechen. Für das obige Beispiel sind die erwarteten Ergebnisse:

{ 
    "conflicts": [ 
    { 
     "num_of_books": 2, 
     "count": "1" 
    }, 
    { 
     "num_of_books": 1, 
     "count": "3" 
    } 
    ] 
} 

Der Eintrag mit num_of_books von 2 ist der Konflikt von „Animal Farm“, und es geschah einmal (also die count ist 1). Die anderen 3 Bücher haben alle unterschiedliche Namen, daher erscheinen sie im Eintrag mit num_of_books von 1 und count von 3. I nicht brauchen die Namen der Bücher. Nur die Anzahl zählt.

I SQL wissen muss „Unterabfrage“, dies zu tun:

SELECT num_of_books, COUNT(*) AS _count 
FROM (
    SELECT COUNT(*) AS num_of_books 
    FROM books 
    GROUP BY name 
) 
GROUP BY num_of_books; 

Ich lese die Artikel von Nested Aggregation und Sub-Aggregations, aber nicht die Möglichkeit, um zu sehen, mein Ziel zu erreichen.

Jeder Kommentar wird helfen, danke!

Antwort

0

Laufende Aggregationen auf Aggregationen sind in ES bisher nicht möglich, soweit ich weiß. Ich kenne einige offene Fragen, die es erlauben, zusätzliche Logik auf die Ergebnisse von Bucket-Aggregationen anzuwenden, aber sie werden immer noch diskutiert und diskutiert.

In Ihrem Fall können Sie die innere SQL-Abfrage mit einer terms Aggregation durchkommen, um den Namen aller widersprüchlichen Bücher zu erhalten, indem Sie min_doc_count: 2 verwenden.

{ 
    "size": 0, 
    "aggs": { 
     "books": { 
      "terms": { 
       "field": "name", 
       "min_doc_count": 2 
      } 
     } 
    } 
} 

Dann können Sie die Eimer auf der Client-Seite und wieder Eimer in neue num_of_books Eimer analysieren auf ihre Zählung abhängig. Zum Beispiel mit dem Kopf-Plugin können Sie den folgenden Code in dem Abschnitt Trans hinzufügen

var num_of_books = {}; 
root.aggregations.books.buckets.forEach(function(b) { 
    num_of_books[b.doc_count] = (num_of_books[b.doc_count] || 0) + 1; 
}); 
return num_of_books; 

num_of_books würde dann etwa wie folgt enthalten:

{ 
    "2": 1, 
    "1": 3 
} 
+0

Vielen Dank für die Antwort, aber die Menge der Daten wouldn erlaube mir nicht, die äußere Aggregation auf der Client-Seite zu machen. Gibt es eine Möglichkeit, alle Berechnungen auf dem Server durchzuführen? Wie mit Skriptfeldern? –

+0

Nur für den Anfang, haben Sie versucht, was ich vorschlage, nur um zu sehen, was die Leistung ergibt? Mit dem Kopf-Plugin können Sie in weniger als einer Minute überprüfen, wie es funktioniert. – Val

+0

Ja, ich habe Ihre Lösung ausprobiert und es dauert zu lange, bis meine Kunden darauf warten. Ich brauche die Berechnung in weniger als 10 Sekunden. –

Verwandte Themen