2014-11-05 3 views
12

Wie bekomme ich das erste Element im Array und gebe es im Mongo-Aggregat zurück?Holen Sie das erste Element in Array und Rückgabe mit Aggregate? (Mongodb)

Ich versuche, diesen Code in Mongo laufen, aber fehlschlagen:

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

OBS: 'my_field' ist ein Array mit 4-Position, muss ich es nur das erste Element zurück.

Return:

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

Antwort

3

Derzeit ist die $slice Betreiber ist nicht verfügbar, in dem die $project Betrieb der Aggregation Pipeline. Was könnten Sie tun, ist,

Erste $unwind, die my_field Array, und dann die Gruppe sie zusammen und nehmen Sie die $first Element der Gruppe.

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

Oder den find() Befehl, in dem Sie die Verwendung des $ slice Operators im projection Teil machen könnten.

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

aktualisieren: basierend auf Ihre Kommentare, sagen Sie in einem Array nur die second Artikel wollen, für die Aufzeichnung mit einer ID, id.

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

Dann wird der unter Aggregation Befehl gibt Ihnen das zweite Element in dem my_field Array des Datensatz mit den _id, id.

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

Die obige Logik für mehr einen Datensatz wird nicht angewandt, da es einen $group, Operator nach $unwind verbunden wäre. Der Operator $group erzeugt einen einzelnen Datensatz für alle Datensätze in dieser bestimmten Gruppe, wodurch die Operatoren $limit oder $skip in den späteren Phasen als unwirksam gelten.

Eine kleine Variation der obigen Abfrage find() würde Ihnen ebenfalls das erwartete Ergebnis liefern.

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

Abgesehen von diesen gibt es immer eine Möglichkeit, es in der Client-Seite zu tun, wenn auch ein bisschen teuer, wenn die Anzahl der Datensätze sehr groß ist:

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

aus den oben genannten Optionen Die Wahl hängt auf Ihre Datengröße und App-Design.

+0

Sie beantwortet meine Frage, ohne mein Problem leider zu lösen. Ich brauchte ein generisches Aggregat, in dem ein Parameter definiert, welches Element von $ my_field ich zurückgeben werde. Ich versuche '$ skip' hinzuzufügen, aber es ist kein '$ group'-Operator. –

+0

Siehe meine aktualisierte Antwort. Jedenfalls dachte ich, mein erster Beitrag hätte deine Frage beantwortet. Wenn Sie weitere Erläuterungen benötigen, können Sie Ihre Frage jederzeit aktualisieren oder eine neue Frage hinzufügen. – BatScream

1

Die $ slice Betreiber sollen im $ Projizierungsoperation in Mongo 3.1.4, nach diesem Ticket zur Verfügung gestellt werden: https://jira.mongodb.org/browse/SERVER-6074

Dies wird das Problem weggehen.

Diese Version ist derzeit nur eine Entwicklerversion und ist noch nicht stabil (Stand Juli 2015). Erwarte dies um Oktober/November Zeit.

0

Mongo ab 3.1.6,

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

wo 0 der Index Anfang und 1 ist die Anzahl der Elemente

9

Seit 3.2 zu schneiden, wir $arrayElemAt bekommen das erste Element in ein verwenden können Array

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