2012-06-22 9 views
15

Diciamo che ho il seguente schema di documento in una raccolta chiamata 'utenti':MongoDB: interrogazione e recupero di oggetti all'interno dell'array incorporato?

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

L'array 'voci' contiene oggetti nel seguente formato:

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

Ogni utente può avere più elementi incorporato nell'array 'items'.

Ora, voglio essere in grado di recuperare un oggetto da un item_id per un dato utente.

Ad esempio, desidero ottenere l'elemento con ID "1234" appartenente all'utente con il nome "John".

Posso farlo con mongoDB? Mi piacerebbe utilizzare la sua potente indicizzazione di array, ma non sono sicuro che sia possibile eseguire query su array incorporati e restituire oggetti dall'array invece del documento che lo contiene.

So che posso recuperare gli utenti che hanno un determinato oggetto utilizzando {users.items.item_id: "1234"}. Ma voglio recuperare l'oggetto reale dall'array, non l'utente.

In alternativa, c'è forse un modo migliore per organizzare questi dati in modo da poter ottenere facilmente ciò che voglio? Sono ancora abbastanza nuovo per mongodb.

Grazie per qualsiasi aiuto o consiglio che è possibile fornire.

+0

possibile duplicato del [MongoDB estrarre solo l'elemento selezionato in ordine] (http: // stackoverflow.com/questions/3985214/mongodb-extract-only-the-selected-item-in-array) – Foreever

+0

Ciao, @Nebs, puoi rivedere la risposta accettata e modificarla? Perché c'è una soluzione a questo problema senza bisogno di due raccolte separate nelle versioni più recenti di mongodb. –

risposta

22

La domanda è vecchia, ma la risposta è cambiata dal tempo. Con MongoDB> = 2.2, si può fare:

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

TU AVRAI:

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

See Documentation of $elemMatch

+2

Questa è la migliore risposta alla domanda dell'OP, spero che la veda e la modifichi, altrimenti molte persone guarderanno la risposta accettata e pensano che non ci sia soluzione senza due raccolte . –

1

Se si tratta di un array incorporato, non è possibile recuperarne direttamente gli elementi. Il documento recuperato avrà la forma di un utente (documento root), sebbene non tutti i campi possano essere compilati (a seconda della query).

Se si desidera recuperare solo quell'elemento, è necessario memorizzarlo come documento separato in una raccolta separata. Avrà un campo aggiuntivo, user_id (può essere parte di _id). Quindi è banale fare quello che vuoi.

Un documento di esempio potrebbe essere simile a questo:

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

Si noti che questa struttura assicura unicità di item_id per utente (non sono sicuro che si desidera o no).

+2

Grazie per la risposta. Volevo evitare di utilizzare due raccolte per questo, ma sembra che sia l'unico modo. – nebs

6

Ci sono un paio di cose da notare su questo:

1) Trovo che la cosa più difficile per la gente di apprendimento MongoDB è ONU-learning il pensiero relazionale che sono abituati. Il tuo modello di dati sembra essere quello giusto.

2) Normalmente, ciò che si fa con MongoDB è restituire l'intero documento nel programma client, quindi cercare la parte del documento che si desidera sul lato client utilizzando il linguaggio di programmazione client.

Nell'esempio, è necessario recuperare l'intero documento "utente" e quindi scorrere l'array "items []" sul lato client.

3) Se si desidera restituire solo l'array 'items []', è possibile farlo utilizzando la sintassi 'Selezione campo'. Vedi http://www.mongodb.org/display/DOCS/Querying#Querying-FieldSelection per i dettagli. Sfortunatamente, restituirà l'intero array 'items []', e non solo un elemento dell'array.

4) È disponibile un ticket Jira esistente per aggiungere questa funzionalità: è https://jira.mongodb.org/browse/SERVER-828 SERVER-828. Sembra che sia stato aggiunto alla sezione 2.1 (sviluppo) più recente: ciò significa che sarà disponibile per l'uso di produzione quando verrà rilasciata la versione 2.2.

+0

Questa è una risposta fantastica spero sia ancora attuale –

Problemi correlati