2012-06-22 12 views
15

Powiedzmy mam następujący schemat dokumentu w kolekcji o nazwie „użytkownicy”:MongoDB: Zapytanie i pobieranie obiektów w osadzonej macierzy?

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

Tablica „przedmioty” zawiera obiekty w następującym formacie:

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

Każdy użytkownik może posiadać kilka pozycji osadzone w tablicy "items".

Teraz chcę mieć możliwość pobrania elementu item_id dla danego użytkownika.

Na przykład chcę uzyskać element o identyfikatorze "1234", który należy do użytkownika o nazwie "John".

Czy mogę to zrobić z mongoDB? Chciałbym wykorzystać jego potężne indeksowanie tablicowe, ale nie jestem pewien, czy można uruchamiać kwerendy na osadzonych tablicach i zwracać obiekty z tablicy zamiast dokumentu, który ją zawiera.

Wiem, że mogę pobrać użytkowników, którzy mają określony produkt za pomocą {users.items.item_id: "1234"}. Ale chcę pobrać rzeczywisty element z tablicy, a nie użytkownika.

Czy istnieje lepszy sposób uporządkowania tych danych, aby móc łatwo uzyskać to, czego chcę? Nadal jestem całkiem nowy w mongodb.

Dziękujemy za udzielenie pomocy lub porady.

+0

możliwe duplikat [MongoDB wyodrębnić tylko wybrany element w tablicy] (http: // stackoverflow.com/questions/3985214/mongodb-extract-only-the-selected-item-in-array) – Foreever

+0

Witaj, @Nebs, czy możesz przejrzeć zaakceptowaną odpowiedź i ją zmienić? Ponieważ istnieje rozwiązanie tego problemu bez potrzeby dwóch oddzielnych kolekcji w nowszych wersjach Mongodb. –

Odpowiedz

22

Pytanie jest stare, ale odpowiedź zmieniła się od czasu. Z MongoDB> = 2.2, można zrobić:

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

Trzeba będzie:

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

See Documentation of $elemMatch

+2

To jest najlepsza odpowiedź na pytanie OP, mam nadzieję, że widzi i zmienia to, w przeciwnym razie wielu ludzi spojrzy na zaakceptowaną odpowiedź i myśli, że nie ma rozwiązania bez dwóch kolekcji . –

1

Jeśli jest to osadzona tablica, to nie można bezpośrednio pobrać jej elementów. Pobrany dokument będzie miał postać użytkownika (dokument główny), chociaż nie wszystkie pola mogą być wypełnione (w zależności od zapytania).

Jeśli chcesz odzyskać tylko ten element, musisz przechowywać go jako osobny dokument w osobnej kolekcji. Będzie mieć jedno dodatkowe pole, user_id (może być częścią _id). W takim razie robienie tego, co chcesz, jest trywialne.

przykładowy dokument może wyglądać następująco:

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

pamiętać, że ta struktura zapewnia niepowtarzalność item_id każdego użytkownika (nie jestem pewien, że chcesz tego, czy nie).

+2

Dzięki za odpowiedź. Chciałem uniknąć do tego dwóch kolekcji, ale wygląda na to, że to jedyny sposób. – nebs

6

Istnieje kilka rzeczy, aby pamiętać o tym:

1) Uważam, że najtrudniejszą rzeczą dla ludzi uczących MongoDB jest ONZ-learning relacyjnej myślenia, że ​​jesteśmy przyzwyczajeni. Twój model danych wygląda na właściwy.

2) Zwykle to, co robisz z MongoDB, powoduje zwrócenie całego dokumentu do programu klienckiego, a następnie wyszukanie fragmentu dokumentu, który ma być po stronie klienta, przy użyciu języka programowania klienta.

W tym przykładzie pobierasz cały dokument "użytkownika", a następnie powtarzasz tablicę "items []" po stronie klienta.

3) Jeśli chcesz zwrócić tylko tablicę "items []", możesz to zrobić, używając składni "Wybór pola". Aby uzyskać szczegółowe informacje, patrz http://www.mongodb.org/display/DOCS/Querying#Querying-FieldSelection. Niestety zwróci ona całą tablicę "items []", a nie tylko jeden element tablicy.

4) Istnieje istniejący bilet Jira, aby dodać tę funkcję: jest to https://jira.mongodb.org/browse/SERVER-828 SERVER-828. Wygląda na to, że został dodany do najnowszej gałęzi 2.1 (rozwojowej): oznacza to, że będzie dostępny do użytku produkcyjnego, gdy wersja 2.2 zostanie dostarczona.

+0

To jest fantastyczna odpowiedź, mam nadzieję, że nadal jest istotna. –

Powiązane problemy