Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to project array index after unwinding an array with MongoDB aggregation framework

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?

like image 572
Roland Bouman Avatar asked Dec 27 '14 01:12

Roland Bouman


People also ask

How do you unwind an array of arrays in MongoDB?

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.

Does MongoDB aggregate use index?

An aggregation pipeline can use indexes from the input collection to improve performance. Using an index limits the amount of documents a stage processes.

How do you unwind an array of objects in MongoDB?

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.

What is unwind in MongoDB aggregation?

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 .


2 Answers

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>
  }
}
like image 140
Alain1405 Avatar answered Oct 16 '22 20:10

Alain1405


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]});
    }
}
like image 3
BatScream Avatar answered Oct 16 '22 22:10

BatScream