Interrogare la dimensione dell’array interno in MongoDB

Considera un documento MongoDB nella raccolta degli users :

 { username : 'Alex', tags: ['C#', 'Java', 'C++'] } 

C’è un modo, per ottenere la lunghezza della serie di tags dal lato server (senza passare i tag al client)?

Grazie!

Ora MongoDB (versione 2.6) supporta l’ operazione $size in aggregazione.

Dalla documentazione:

 { : { $size:  } } 

Quello che vuoi può essere ottenuto seguendo o usando questo:

 db.users.aggregate( [ { $group: { _id: "$username", tags_count: {$first: {$size: "$tags" }} } } ] ) 

o

 db.users.aggregate( [ { $project: { tags_count: {$size: "$tags"} } } ] ) 

se il nome utente Alex è unico, puoi usare il seguente codice:

 db.test.insert({username:"Alex", tags: ['C#', 'Java', 'C++'] }); db.test.aggregate( {$match: {username : "Alex"}}, {$unwind: "$tags"}, {$project: {count:{$add:1}}}, {$group: {_id: null, number: {$sum: "$count" }}} ); { "result" : [ { "_id" : null, "number" : 3 } ], "ok" : 1 } 

Penso che potrebbe essere più efficiente calcolare il numero di tag su ciascun salvataggio (come campo separato) usando $ inc forse o tramite un lavoro su una pianificazione.

Puoi anche farlo con map / reduce (l’ esempio canonico ) ma non sembra essere quello che vorresti.

Non sono sicuro che sia ansible fare esattamente quello che stai chiedendo, ma puoi interrogare tutti i documenti che corrispondono a una determinata dimensione con $ size …

 > db.collection.find({ tags : { $size: 3 }}); 

Avresti tutti i documenti con 3 tag …

La risposta di xmm.dev può essere semplificata: invece di avere il conteggio dei campi interm, puoi sumre direttamente in $ group:

 db.test.aggregate( {$match: {username : "Alex"}}, {$unwind: "$tags"}, {$group: {_id: null, number: {$sum: 1 }}} ) 

Attualmente, l’unico modo per farlo sembra usare db.eval , ma questo blocca il database per altre operazioni .

Il modo più efficiente in termini di velocità consisterebbe nell’aggiungere un campo aggiuntivo che memorizza la lunghezza della matrice e la mantiene mediante le operazioni $ inc e $ push .

Ho fatto un piccolo lavoro in giro perché avevo bisogno di interrogare la dimensione dell’array e restituire se era maggiore di 0 ma poteva essere qualsiasi cosa da 1-3.

Ecco la mia soluzione:

 db.test.find($or : [{$field : { $exists : true, $size : 1}}, {$field : { $exists : true, $size : 2}}, {$field : { $exists : true, $size : 3}}, ]) 

Questo in sostanza restituisce un documento quando l’attributo esiste e la dimensione è 1, 2 o 3. L’utente può aggiungere più istruzioni e incrementare se sta cercando una dimensione specifica o all’interno di un intervallo. So che non è perfetto ma ha funzionato ed è stato relativamente veloce. Ho avuto solo 1-3 dimensioni nel mio attributo, quindi questa soluzione ha funzionato.