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?
The $unwind operator is used to deconstructing an array field in a document and create separate output documents for each item in the array. The only difference between input and output documents is that the value of the array field in output documents is replaced with a single item from the input document array.
An aggregation pipeline can use indexes from the input collection to improve performance. Using an index limits the amount of documents a stage processes.
The MongoDB $unwind stages operator is used to deconstructing an array field from the input documents to output a document for each element. Every output document is the input document with the value of the array field replaced by the element. Points to remember: If the value of a field is not an array, db.
The operation unwinds the sizes array and includes the array index in the new arrayIndex field. If the sizes field does not resolve to a populated array but is not missing, null, or an empty array, the arrayIndex field is null .
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>
}
}
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]});
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With