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

Der effizienteste Weg, verschachtelte Kategorien (oder hierarchische Daten) in Mongo zu speichern?

Das erste, was Sie entscheiden sollten, ist genau, welche Art von Baum Sie verwenden werden.

Das Wichtigste, was Sie berücksichtigen sollten, sind Ihre Daten und Zugriffsmuster. Sie haben bereits gesagt, dass 90 % Ihrer gesamten Arbeit mit Abfragen und dem Anschein nach (E-Commerce-)Updates nur von Administratoren ausgeführt werden, höchstwahrscheinlich selten.

Sie möchten also ein Schema, das Ihnen die Möglichkeit gibt, Kinder schnell über einen Pfad abzufragen, z. B.:Sport -> Basketball -> Männer, Sport -> Tennis -> Frauen, und nicht wirklich auf Aktualisierungen skalieren muss /P>

Wie Sie so richtig darauf hingewiesen haben, hat MongoDB eine gute Dokumentationsseite dafür:https://docs.mongodb.com/manual/applications/data-models-tree-structures/ wobei 10gen tatsächlich verschiedene Modelle und Schemamethoden für Bäume angibt und die wichtigsten Höhen und Tiefen von ihnen beschreibt.

Derjenige, der ins Auge fallen sollte, wenn Sie nach einfachen Abfragen suchen, sind materialisierte Pfade:https://docs.mongodb.com/manual/tutorial/model-tree-structures-with-materialized-paths/

Dies ist eine sehr interessante Methode, um Bäume aufzubauen, da Sie zum Abfragen des Beispiels, das Sie oben gegeben haben, in „Frauen“ in „Tennis“ einfach eine vorangestellte Regex verwenden könnten (die den Index verwenden kann:http://docs.mongodb.org/manual/reference/operator/regex/ ) so:

db.products.find({category: /^Sports,Tennis,Womens[,]/})

um alle Produkte zu finden, die unter einem bestimmten Pfad Ihres Stammbaums aufgelistet sind.

Leider ist dieses Modell wirklich schlecht bei der Aktualisierung, wenn Sie eine Kategorie verschieben oder ihren Namen ändern, müssen Sie alle Produkte aktualisieren und es könnten Tausende von Produkten in einer Kategorie sein.

Eine bessere Methode wäre, eine cat_id unterzubringen auf dem Produkt und trennen Sie dann die Kategorien in eine separate Sammlung mit dem Schema:

{
    _id: ObjectId(),
    name: 'Women\'s',
    path: 'Sports,Tennis,Womens',
    normed_name: 'all_special_chars_and_spaces_and_case_senstive_letters_taken_out_like_this'
}

Ihre Abfragen betreffen jetzt also nur die Kategoriensammlung, wodurch sie viel kleiner und leistungsfähiger werden sollten. Die Ausnahme hiervon ist, wenn Sie eine Kategorie löschen, müssen die Produkte immer noch berührt werden.

Ein Beispiel für die Änderung von „Tennis“ in „Badmin“:

db.categories.update({path:/^Sports,Tennis[,]/}).forEach(function(doc){
    doc.path = doc.path.replace(/,Tennis/, ",Badmin");
    db.categories.save(doc);
});

Leider bietet MongoDB im Moment keine Dokumentreflektion in Abfragen, so dass Sie sie clientseitig herausziehen müssen, was ein wenig ärgerlich ist, aber hoffentlich sollte es nicht dazu führen, dass zu viele Kategorien zurückgebracht werden.

Und so funktioniert es im Grunde wirklich. Das Aktualisieren ist ein bisschen mühsam, aber die Möglichkeit, mithilfe eines Indexes sofort auf jedem Pfad Abfragen zu können, passt meiner Meinung nach besser zu Ihrem Szenario.

Der zusätzliche Vorteil ist natürlich, dass dieses Schema mit verschachtelten Mengenmodellen kompatibel ist:http://en.wikipedia .org/wiki/Nested_set_model die ich immer wieder gefunden habe, sind für E-Commerce-Sites einfach großartig, zum Beispiel könnte Tennis sowohl unter "Sport" als auch unter "Freizeit" sein und Sie möchten mehrere Pfade, je nachdem, woher der Benutzer kommt.

Das Schema für materialisierte Pfade unterstützt dies einfach, indem einfach ein weiterer path hinzugefügt wird , so einfach.

Hoffe, es macht Sinn, da ist es ziemlich lang.