MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

Optimierung von MongoDB-Abfragen

Was Sie wollen, ist ein "facettiertes Suchergebnis", in dem Sie die Statistiken über die übereinstimmenden Begriffe in der aktuellen Ergebnismenge speichern. Obwohl es Produkte gibt, die scheinbar die ganze Arbeit in einer einzigen Antwort erledigen, müssen Sie bedenken, dass die meisten generischen Speicher-Engines mehrere Vorgänge benötigen.

Mit MongoDB können Sie zwei Abfragen verwenden, um die Ergebnisse selbst abzurufen, und eine weitere, um die Facetteninformationen abzurufen. Dies würde ähnliche Ergebnisse wie die facettierten Ergebnisse liefern, die von dedizierten Suchmaschinenprodukten wie Solr oder ElasticSearch verfügbar sind.

Um dies jedoch effektiv zu tun, möchten Sie dies so in Ihr Dokument aufnehmen, dass es effektiv verwendet werden kann. Eine sehr effektive Form für das, was Sie wollen, ist die Verwendung eines Arrays von tokenisierten Daten:

 {
     "otherData": "something",
     "facets": [
         "country:UK",
         "city:London-UK",
         "genre:Student"
     ]
 }

„factets“ ist also ein einzelnes Feld in Ihrem Dokument und nicht an mehreren Stellen. Dies macht es sehr einfach zu indizieren und abzufragen. Dann können Sie Ihre Ergebnisse effektiv aggregieren und die Summen für jede Facette abrufen:

User.aggregate(
    [
        { "$unwind": "$facets" },
        { "$group": {
            "_id": "$facets",
            "count": { "$sum": 1 }
        }}
    ],
    function(err,results) {

    }
);

Oder idealerweise mit einigen Kriterien in $match :

User.aggregate(
    [
        { "$match": { "facets": { "$in": ["genre:student"] } } },
        { "$unwind": "$facets" },
        { "$group": {
            "_id": "$facets",
            "count": { "$sum": 1 }
        }}
    ],
    function(err,results) {

    }
);

Letztendlich gibt man eine Antwort wie:

{ "_id": "country:FR", "count": 50 },
{ "_id": "country:UK", "count": 300 },
{ "_id": "city:London-UK", "count": 150 },
{ "_id": "genre:Student": "count": 500 }

Eine solche Struktur ist leicht zu durchqueren und auf Dinge wie das diskrete „Land“ und die „Stadt“, die zu einem „Land“ gehört, zu untersuchen, da diese Daten nur konsequent durch einen Bindestrich „-“ getrennt werden.

Der Versuch, Dokumente innerhalb von Arrays zusammenzufassen, ist eine schlechte Idee. Es gibt auch eine BSON-Größenbeschränkung von 16 MB, die respektiert werden muss, ab der das Zusammenfügen von Ergebnissen (insbesondere wenn Sie versuchen, Dokumentinhalte zu behalten) höchstwahrscheinlich in der Antwort überschritten wird.

Für etwas so Einfaches wie das Abrufen der „Gesamtzahl“ der Ergebnisse einer solchen Abfrage summieren Sie einfach die Elemente eines bestimmten Facettentyps. Oder geben Sie einfach dieselben Abfrageargumente an .count() aus Betrieb:

User.count({ "facets": { "$in": ["genre:Student"] } },function(err,count) {

});

Wie hier gesagt, werden insbesondere bei der Implementierung von "Paging" von Ergebnissen die Rollen des Abrufens von "Result Count", "Facet Counts" und der eigentlichen "Page of Results" alle an "separate" Abfragen an den Server delegiert.

Es ist nichts Falsches daran, jede dieser Abfragen parallel an den Server zu senden und dann eine Struktur zu kombinieren, um sie Ihrer Vorlage oder Anwendung zuzuführen, die dem facettierten Suchergebnis von einem der Suchmaschinenprodukte ähnelt, das diese Art von Antwort bietet.

Abschluss

Fügen Sie also etwas in Ihr Dokument ein, um die Facetten an einer einzigen Stelle zu markieren. Ein Array tokenisierter Zeichenfolgen eignet sich gut für diesen Zweck. Es funktioniert auch gut mit Abfrageformen wie $in und $all entweder für „oder“- oder „und“-Bedingungen für Facettenauswahlkombinationen.

Versuchen Sie nicht, Ergebnisse zu zerkleinern oder Ergänzungen zu verschachteln, nur um einer wahrgenommenen hierarchischen Struktur zu entsprechen, sondern durchlaufen Sie die erhaltenen Ergebnisse und verwenden Sie einfache Muster in den Token. Es ist sehr einfach,

Führen Sie seitenweise Abfragen für den Inhalt als separate Abfragen für Facetten oder Gesamtzahlen aus. Der Versuch, alle Inhalte in Arrays zu verschieben und dann nur auf die Anzahl zu beschränken, macht keinen Sinn. Dasselbe würde für eine RDBMS-Lösung gelten, um dasselbe zu tun, wobei die Anzahl der Paging-Ergebnisse und die aktuelle Seite separate Abfrageoperationen sind.

Im MongoDB-Blog finden Sie weitere Informationen zur facettierten Suche mit MongoDB, die auch einige andere Optionen erläutern. Es gibt auch Artikel zur Integration mit externen Suchlösungen mit Mongoconnector oder anderen Ansätzen.