Holt Dokumente mit Tags in der Liste, sortiert nach der Gesamtzahl der Übereinstimmungen

8

Angesichts der folgenden MongoDB-Sammlung von Dokumenten:

%Vor%

Wie erhalten Sie eine Liste von Elementen, die mit einer Liste von Tags übereinstimmen, sortiert nach der Gesamtzahl übereinstimmender Tags? Zum Beispiel, angesichts dieser Liste von Tags als Eingabe:

%Vor%

Ich möchte die Artikel in der Reihenfolge nach der Anzahl der übereinstimmenden Tags sortieren:

%Vor%

In einem relationalen Schema wären Tags eine separate Tabelle, und Sie könnten sich gegen diese Tabelle anmelden, die Übereinstimmungen zählen und nach der Anzahl sortieren.

Aber in Mongo ...?

Scheint, dieser Ansatz könnte funktionieren,

  • Unterbricht die Eingabe-Tags in mehrere "IN" -Anweisungen
  • Abfrage nach Elementen durch "ODER" zusammen die Tag-Eingaben
    • d. wo ('Shirt' IN items.tags) ODER ('cotton' IN items.tags)
    • Dies würde beispielsweise drei Instanzen von "Shirt One", zwei Instanzen von "Shirt Three" usw. zurückgeben
  • map / reduziere diese Ausgabe
    • map: emit (this._id, {...});
    • reduce: Gesamte Vorkommen von _id
    • zählen
    • finalize: Nach Gesamtanzahl sortieren

Aber mir ist nicht klar, wie man das als Mongo-Abfrage implementiert, oder ob dies sogar der effizienteste Ansatz ist.

    
Matt 23.12.2011, 14:45
quelle

3 Antworten

7

Wie ich in Suchen Sie in MongoDB in einem Array und sortieren Sie nach der Anzahl der Übereinstimmungen

Es ist möglich, Aggregation Framework zu verwenden.

Annahmen

  • tags Attribut ist eine Menge (keine wiederholten Elemente)

Abfrage

Bei diesem Ansatz müssen Sie die Ergebnisse abwickeln und das Match-Prädikat mit nicht abgeglichenen Ergebnissen neu bewerten, sodass es wirklich ineffizient ist.

%Vor%

Erwartete Ergebnisse

%Vor%     
Samuel García 13.09.2012 15:23
quelle
5

Derzeit ist es nicht möglich, MapReduce zu verwenden. Das einzige Problem mit MapReduce ist, dass es langsam ist (verglichen mit einer normalen Abfrage).

Das Aggregationsframework ist für 2.2 vorgesehen (sollte in 2.1 dev release verfügbar sein) und sollte diese Art von Dingen ohne MapReduce viel einfacher machen.

Ich persönlich glaube nicht, dass die Verwendung von M / R ein effizienter Weg ist. Ich würde lieber alle Dokumente abfragen und diese Berechnungen auf der Anwendungsseite durchführen. Es ist einfacher und kostengünstiger, Ihre App-Server zu skalieren, als Ihre Datenbankserver zu skalieren. Lassen Sie die App-Server also die Zahlen knacken. Unter diesen Umständen funktioniert dieser Ansatz bei Ihren Datenzugriffsmustern und -anforderungen möglicherweise nicht.

Ein noch einfacherer Ansatz könnte darin bestehen, einfach eine count -Eigenschaft in jedes Ihrer Tag-Objekte aufzunehmen, und wenn Sie $push ein neues Tag für das Array haben, dann haben Sie auch $inc die count -Eigenschaft. Dies ist ein allgemeines Muster in der MongoDB-Welt, zumindest bis zum Aggregations-Framework.

    
Bryan Migliorisi 23.12.2011 14:58
quelle
1

Ich werde Bryan als zweitens sagen, dass MapReduce der einzig mögliche Weg ist (und es ist bei weitem nicht perfekt). Aber, falls Sie es dringend brauchen, gehen Sie hier: -)

%Vor%     
Sergio Tulentsev 23.12.2011 15:08
quelle