Get n-th element of an array in MongoDB

As part of my document in MongoDB I'm storing an array of objects. How can I query it for only the 4th element of the array for example? So I don't want the get the entire array out, just the 4th element.


Solution 1:

Use $slice.

db.foo.find({ bar : "xyz" } , { my_array : { $slice : [n , 1] } } )

will retrieve the nth element of the array "my_array" of all documents in the foo collection where bar = "xyz".

Some other examples from the MongoDB documentation:

db.posts.find({}, {comments:{$slice: 5}}) // first 5 comments
db.posts.find({}, {comments:{$slice: -5}}) // last 5 comments
db.posts.find({}, {comments:{$slice: [20, 10]}}) // skip 20, limit 10
db.posts.find({}, {comments:{$slice: [-20, 10]}}) // 20 from end, limit 10

Which you can read here: http://www.mongodb.org/display/DOCS/Retrieving+a+Subset+of+Fields

Solution 2:

You can use the $arrayElemAt operator new in MongoDB 3.2 to return the element at the specified array index.


Demo:

A collection named baskets contains documents that look like this:

{
    "_id" : ObjectId("578f326f6db61a299a383c5a"),
    "fruits" : [
        "apple",
        "mango",
        "banana",
        "apricot",
        "cherry"
    ]
}

The following query return the element at index -2 (second element) in the "fruits" array.

db.baskets.aggregate(
    [
        { "$project": { "matched": { "$arrayElemAt": [ "$fruits", 1 ] } } } 
    ] 
)

which produces

{ 
    "_id" : ObjectId("578f326f6db61a299a383c5a"), 
    "matched" : "mango" 
}

And the following query the element before the last element in the array; thus the element at index -2

db.baskets.aggregate(
    [
        { "$project": { "matched": { "$arrayElemAt": [ "$fruits", -2 ] } } } 
    ] 
)

which yields:

{ 
    "_id" : ObjectId("578f326f6db61a299a383c5a"), 
    "matched" : "apricot" 
}

Solution 3:

Another way to do this is to use the update array syntax. Here, contribs.1 sets the second element in the contribs array to have value ALGOL 58 (Taken from the manual page on update syntax)

db.bios.update(
   { _id: 1 },
   { $set: { 'contribs.1': 'ALGOL 58' } }
)