Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Operator $arrayElemAt in aggregation with Mongo < 3.2

Using the aggregation framework in Mongo,

How can I achieve the same result in Mongo < 3.2 as in Mongo 3.2 with the operation $arrayElemAt?

Example in Mongo 3.2

Collection

{ "_id" : 1, "name" : "dave123", favorites: [ "chocolate", "cake", "butter", "apples" ] }

Query

db.users.aggregate([
   {
     $project:
      {
         name: 1,
         first: { $arrayElemAt: [ "$favorites", 0 ] },
         last: { $arrayElemAt: [ "$favorites", -1 ] }
      }
   }
])

It works fine

But, I have been forced to used Mongo 3.0 so I can't use this operator, which is ideal for what I want to do

Is there any way to accessing an element of an array by index with something like...

Mongo 3.0

Collection

{ "_id" : 1, "name" : "dave123", favorites: [ "chocolate", "cake", "butter", "apples" ] }

Query

db.users.aggregate([
   {
     $project:
      {
         name: 1,
         first: { "$favorites.0" },
         last:  { "$favorites.1" }
      }
   }
])

I tried and it doesn't work, it gives me an empty array.

However, when they are properties rather than indexes it is able to retrieve the values

Any help would be really appreciated.

Thanks

like image 410
ackuser Avatar asked Dec 09 '16 09:12

ackuser


1 Answers

You will need to $unwind, $group and use the $first and $last operators like this:

db.collection.aggregate([
    { "$unwind": "$favorites" },
    { "$group": { 
        "_id": "$_id",
        "first": { "$first": "$favorites" },
        "last": { "$last": "$favorites" }
    }}
])

Or two different queries if $unwind is expensive

var first = db.collection.find({}, {"favorites": { $slice: 1}})
var last = db.collection.find({}, {"favorites": { $slice: -1}})
like image 192
styvane Avatar answered Nov 08 '22 17:11

styvane