Think of this MongoDB document:
{_id:123, "food":[ "apple", "banana", "mango" ]}
Question: How to get the position of mango
in food?
The query should return 2
in above, and don't return the whole document.
Please kindly show the working query.
To index a field that holds an array value, MongoDB creates an index key for each element in the array. These multikey indexes support efficient queries against array fields. Multikey indexes can be constructed over arrays that hold both scalar values [1] (e.g. strings, numbers) and nested documents.
To remove an element, update, and use $pull in MongoDB. The $pull operator removes from an existing array all instances of a value or values that match a specified condition.
Finding indexes You can find all the available indexes in a MongoDB collection by using the getIndexes method. This will return all the indexes in a specific collection. Result: The output contains the default _id index and the user-created index student name index.
MongoDB uses multikey indexes to index the content stored in arrays. If you index a field that holds an array value, MongoDB creates separate index entries for every element of the array. These multikey indexes allow queries to select documents that contain arrays by matching on element or elements of the arrays.
Starting from MongoDB version 3.4 we can use the $indexOfArray
operator to return the index at which a given element can be found in the array.
$indexOfArray
takes three arguments. The first is the name of the array field prefixed with $
sign.
The second is the element and the third optional is the index to start the search at. $indexOfArray
returns the first index at which the element is found if the index to start the search at is not specified.
Demo:
> db.collection.insertOne( { "_id" : 123, "food": [ "apple", "mango", "banana", "mango" ] } )
{ "acknowledged" : true, "insertedId" : 123 }
> db.collection.aggregate( [ { "$project": { "matchedIndex": { "$indexOfArray": [ "$food", "mango" ] } } } ] )
{ "_id" : 123, "matchedIndex" : 1 }
> db.collection.aggregate( [ { "$project": { "matchedIndex": { "$indexOfArray": [ "$food", "mango", 2 ] } } } ] )
{ "_id" : 123, "matchedIndex" : 3 }
> db.collection.aggregate( [ { "$project": { "matchedIndex": { "$indexOfArray": [ "$food", "apricot" ] } } } ] )
{ "_id" : 123, "matchedIndex" : -1 }
There really is no other way ( "server side" ) than using mapReduce
:
db.collection.mapReduce(
function() {
emit(this._id, this.food.indexOf("mango"));
},
function() {}, // reducer never gets called since all _id is unique
{
"out": { "inline": 1 },
"query": { "food": "mango" }
}
)
It is the only thing that will return something else in a modified form other than the document itself, as well as using the needed JavaScript evaluation in order to determine the answer,
There is unfortunately no "native" operator that will do this.
Unless you need this for real aggregation purposes, then it is better to just do a similar "array index match" in native code in your client when dealing on a "per document" basis.
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