9

Is it possible to access the array index when unwinding an array (http://docs.mongodb.org/manual/reference/operator/aggregation/unwind/#pipe._S_unwind) using the MongoDB aggregation pipeline?

For example, suppose I'm unwinding this document in collection "c":

{_id: 1, elements: ["a", "b", "c"]}

then this operation:

db.c.aggregate([
 {$unwind: "$elements"}
])

will return a cursor for documents:

[
 {_id: 1, elements: "a"},
 {_id: 1, elements: "b"},
 {_id: 1, elements: "c"}
]

I'd like to be able to figure out aftewards that "a" had index 0, "b" had index 1 and "c" had index "2" in the original array before unwinding.

How can I project the array index in an unwinding operation?

2 Answers 2

15

The newly released MongoDB 3.2 supports unwinding of the array index.

Instead of passing a path the $unwind operator, you can pass an object with the field path and the field includeArrayIndex which will hold the array index.

From MongoDB official documentation:

{
  $unwind:
  {
    path: <field path>,
    includeArrayIndex: <string>,
    preserveNullAndEmptyArrays: <boolean>
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Is there a possible to reverse this operation in Aggregation? or The solution for projecting array is not possible in Mongodb, but code as Accepted. Sorry, I mean reversing unwind.
@Tokenyet, shortly: yes, it's possible, e.g. if you unwinded field elements, then you can combine it back like this { $group: { _id: '$_id', elements: { $push: '$elements' } } }. Would be great if you can submit it as a separate question (not just a comment) so that I can give the full answer there.
3

Currently this seems to be not possible using the aggregation framework. There is an unresolved open issue linked to it: https://jira.mongodb.org/browse/SERVER-4588.

As a workaround you could use Map-reduce, with the map function assigning an index to each array element.

var map = function(){
    for(var i=0;i<this.elements.length;i++){
    emit({"_id":this._id,"index":i},{"index":i,"value":this.elements[i]});
    }
}

3 Comments

Thank you! I got the impression it wasn't possible since I saw now examples nor found any operator to project the index. But I didnt find this issue report yet. Thanks!
You're most welcome. A combination of operators, $let and $map can take us close to project manipulated values but due to their scope restrictions, incremental indexing can't be achieved.
I'm aware that with map/reduce one can do virtually anything within the limits of the map/reduce implementation. One thing that keeps puzzling me is how to ensure the map result doesn't get too large. With regard to the problem at hand, I think that JIRA case proposes a reasonable way to project the index. So far, I'm experiencing a pretty steep learning curve learning to query MongoDB.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.