2012-06-22 8 views
15

Lassen Sie uns sagen, dass ich das folgende Dokument-Schema in einer Sammlung ‚Nutzer‘ genannt haben:MongoDB: Abfrage und Abruf von Objekten innerhalb eines eingebetteten Arrays?

{ 
    name: 'John', 
    items: [ {}, {}, {}, ... ] 
} 

Die ‚Elemente‘ Array enthält Objekte in folgendem Format:

{ 
    item_id: "1234", 
    name: "some item" 
} 

Jeder Benutzer mehrere Elemente haben können eingebettet in das Array 'Elemente'.

Jetzt möchte ich in der Lage sein, ein Element durch eine item_id für einen bestimmten Benutzer abzurufen.

Zum Beispiel möchte ich den Artikel mit der ID "1234", die dem Benutzer mit dem Namen "John" gehören.

Kann ich dies mit mongoDB tun? Ich möchte seine leistungsfähige Array-Indizierung verwenden, aber ich bin mir nicht sicher, ob Sie Abfragen für eingebettete Arrays ausführen und Objekte aus dem Array anstelle des Dokuments zurückgeben können, das sie enthält.

Ich weiß, dass ich mit {users.items.item_id: "1234"} Benutzer abrufen kann, die ein bestimmtes Element haben. Aber ich möchte das tatsächliche Element aus dem Array abrufen, nicht den Benutzer.

Alternativ gibt es vielleicht eine bessere Möglichkeit, diese Daten zu organisieren, so dass ich leicht bekommen kann, was ich will? Ich bin noch ziemlich neu für Mongodb.

Vielen Dank für Ihre Hilfe oder Ihren Rat.

+0

möglich Duplikat [MongoDB nur das ausgewählte Element in Array extrahieren] (http: // stackoverflow.com/questions/3985214/mongodb-extract-only-the-selected-item-in-array) – Foreever

+0

Hallo, @Nebs, können Sie die akzeptierte Antwort überprüfen und ändern? Weil es eine Lösung für dieses Problem gibt, ohne dass zwei separate Sammlungen in neueren Mongodb-Versionen benötigt werden. –

Antwort

22

Die Frage ist alt, aber die Antwort hat sich seit der Zeit geändert. Mit MongoDB> = 2.2 können Sie tun:

db.users.find({ name: "John"}, { items: { $elemMatch: { item_id: "1234" } } }) 

Sie haben:

{ 
    name: "John", 
    items: 
    [ 
     { 
     item_id: "1234", 
     name: "some item" 
     } 
    ] 
} 

See Documentation of $elemMatch

+2

Dies ist die beste Antwort auf die OP-Frage, ich hoffe, er sieht und ändert es, sonst werden viele Leute die akzeptierte Antwort betrachten und denken, dass es keine Lösung ohne zwei Sammlungen gibt . –

1

Wenn dies ein eingebettetes Array ist, können Sie seine Elemente nicht direkt abrufen. Das abgerufene Dokument hat die Form eines Benutzers (Stammdokument), obwohl nicht alle Felder ausgefüllt werden können (abhängig von Ihrer Anfrage).

Wenn Sie nur dieses Element abrufen möchten, müssen Sie es als separates Dokument in einer separaten Sammlung speichern. Es wird ein zusätzliches Feld haben, user_id (kann Teil von _id sein). Dann ist es trivial zu tun, was Sie wollen.

Ein Beispieldokument könnte wie folgt aussehen:

{ 
    _id: {user_id: ObjectId, item_id: "1234"}, 
    name: "some item" 
} 

Beachten Sie, dass diese Struktur von item_id pro Benutzer Eindeutigkeit gewährleistet (Ich bin nicht sicher, dass Sie das wollen oder nicht).

+2

Danke für die Antwort. Ich wollte die Verwendung von zwei Sammlungen vermeiden, aber es sieht so aus, als ob es der einzige Weg ist. – nebs

6

Es gibt ein paar Dinge, über diese zu beachten:

1) Ich finde, dass das härteste, was für Leute lernen MongoDB ist das relationale Denken UN-Learning, die sie gewohnt sind. Ihr Datenmodell scheint der richtige zu sein.

2) Normalerweise, was Sie mit MongoDB tun, ist das gesamte Dokument in das Client-Programm zurückgeben, und dann suchen Sie den Teil des Dokuments auf der Client-Seite mit Ihrer Client-Programmiersprache.

In Ihrem Beispiel würden Sie das gesamte Dokument 'Benutzer' abrufen und dann auf der Client-Seite durch das Array 'items []' iterieren.

3) Wenn Sie nur das Array 'items []' zurückgeben möchten, können Sie dies mithilfe der Syntax 'Feldauswahl' tun. Details siehe http://www.mongodb.org/display/DOCS/Querying#Querying-FieldSelection. Leider wird das gesamte Array 'items []' zurückgegeben und nicht nur ein Element des Arrays.

4) Es gibt ein vorhandenes Jira-Ticket, um diese Funktionalität hinzuzufügen: es ist https://jira.mongodb.org/browse/SERVER-828 SERVER-828. Es sieht so aus, als ob es in den letzten 2.1 (Entwicklungs) Zweig aufgenommen wurde: das bedeutet, dass es für die Produktion verfügbar sein wird, wenn Release 2.2 ausgeliefert wird.

+0

Dies ist eine fantastische Antwort Ich hoffe, es ist noch relevant –

Verwandte Themen