2014-11-05 12 views
12

Come ottengo il primo elemento dell'array e lo restituisco in un aggregato Mongo?Ottieni il primo elemento nella matrice e restituisci utilizzando Aggregazione? (Mongodb)

provo eseguire questo codice in mongo, ma non riescono:

db.my_collection.aggregate([ 
    { $project: { 
     resp : { my_field: { $slice: 1 } } 
    }} 
]) 

OBS: 'my_field' è un array con 4 posizioni, ho bisogno ritorno solo primo elemento.

ritorno:

uncaught exception: aggregate failed: { 
    "errmsg" : "exception: invalid operator '$slice'", 
    "code" : 15999, 
    "ok" : 0 
} 

risposta

3

Attualmente, l'operatore $slice non è disponibile nel funzionamento del $project, del gasdotto aggregazione. Allora, cosa si potrebbe fare è,

In primo luogo $unwind, il my_field array e poi raggrupparli e prendere l'elemento $first del gruppo.

db.my_collection.aggregate([ 
{$unwind:"$my_field"}, 
{$group:{"_id":"$_id","resp":{$first:"$my_field"}}}, 
{$project:{"_id":0,"resp":1}} 
]) 

o utilizzando il comando find(), dove si potrebbe fare uso dell'operatore $ fetta nella parte projection.

db.my_collection.find({},{"my_field":{$slice:1}}) 

Aggiornamento: in base ai vostri commenti, dici che vuoi solo l'elemento second in un array, per il record con un id, id.

var field = 2; 
var id = ObjectId("..."); 

Poi, sotto il comando di aggregazione ti dà la seconda voce nella my_field serie di record con l'_id, id.

db.my_collection.aggregate([ 
{$match:{"_id":id}}, 
{$unwind:"$my_field"}, 
{$skip:field-1}, 
{$limit:1} 
]) 

La logica di cui sopra non può essere applicata per più di un record, poiché ciò comporterebbe un operatore $group dopo $unwind. L'operatore $group produce un singolo record per tutti i record in quel particolare gruppo rendendo inefficaci gli operatori o $skip applicati nelle fasi successive.

Una piccola variazione sopra la query find() fornirebbe anche il risultato previsto.

db.my_collection.find({},{"my_field":{$slice:[field-1,1]}}) 

Oltre a questi, c'è sempre un modo per farlo nel lato client, anche se un po 'costoso, se il numero di record è molto grande:

var field = 2; 
db.my_collection.find().map(function(doc){ 
return doc.my_field[field-1]; 
}) 

scelta tra quelli sopra indicati dipende sulla dimensione dei dati e sulla progettazione dell'app.

+0

Hai risposto alla mia domanda senza risolvere il mio problema, purtroppo. Avevo bisogno di un aggregato generico, in cui un parametro definisce quale elemento di '$ my_field' tornerò. Cerco di aggiungere '$ skip', ma non è un operatore' $ group'. –

+0

Vedere la mia risposta aggiornata. Comunque pensavo che il mio post iniziale avesse risposto alla tua domanda. Se hai richiesto ulteriori chiarimenti, puoi sempre aggiornare la tua domanda o aggiungere una nuova domanda. – BatScream

1

L'operatore porzione $ è prevista per essere messi a disposizione per il funzionamento $ progetto in Mongo 3.1.4, secondo questo biglietto: https://jira.mongodb.org/browse/SERVER-6074

questo renderà il problema andare via.

Questa versione è attualmente solo una versione per sviluppatori e non è ancora stabile (a luglio 2015). Aspettiamoci intorno all'ora di ottobre/novembre.

0

Mongo 3.1.6 in poi,

db.my_collection.aggregate([ 
{ 
    "$project": { 
     "newArray" : { "$slice" : [ "$oldarray" , 0, 1 ] } 
    } 
} 
]) 

dove 0 è l'indice iniziale e 1 è il numero di elementi da affettare

9

Dal 3.2, possiamo usare $arrayElemAt per ottenere il primo elemento di un array

db.my_collection.aggregate([ 
    { $project: { 
     resp : { $arrayElemAt: ['$my_field',0] } 
    }} 
]) 
Problemi correlati