I'm trying to create a projection within a MongoDB aggregation function, see the following:
[
{$match : {"geo" : {$ne: null}}},
{$project : {"id" : "$id_str", lat: "$geo.coordinates.0", lon: "$geo.coordinates.1"}}
]
However when I do this it does not pass over the array item it simply projects an empty array to the properties lat and lon.
What is needed here? I have looked at the Documentation but cannot figure it out, and even tried a permutation of $unwind and $group but with no success.
To search the array of object in MongoDB, you can use $elemMatch operator. This operator allows us to search for more than one component from an array object.
Filter MongoDB Array Element Using $Filter Operator This operator uses three variables: input – This represents the array that we want to extract. cond – This represents the set of conditions that must be met. as – This optional field contains a name for the variable that represent each element of the input array.
Use $match With $eq to Find Matching Documents in an Array in MongoDB. Use $match With $all to Find Matching Documents in an Array in MongoDB.
The feature that will help you achieve this is not yet available. However, there will be a new aggregation operator that gives an array element for a given index. The new expression is called $arrayElemAt
Use the new aggregation operator that's available for MongoDB versions 3.2.X
and greater, this returns an array element for a given index. The new expression is called $arrayElemAt
. It takes two arguments, an array and an index and returns the element at the given index in the array. Negative indices are accepted as indexes from the back of the array. If the index is out of bounds, it returns the missing value, meaning the field will not exist in the output:
var pipeline = [
{ $match : {"geo" : {$ne: null}}},
{
$project: {
_id: "$id_str",
lat: { $arrayElemAt: ['$geo.coordinates', 0] },
lon: { $arrayElemAt: ['$geo.coordinates', 1] }
}
}
];
As a workaround for now (assuming the coordinates array will always have two elements at any given time), you could try the following aggregation pipeline which will take advantage of the $first
and $last
group accumulator operators to get the elements after a $sort
:
var pipeline = [
{$match : {"geo" : {$ne: null}}},
{ "$unwind": "$geo.coordinates" },
{ "$sort": {"geo.coordinates": 1} } ,
{
"$group": {
"_id": "$_id",
"lat": { "$first": "$geo.coordinates" },
"lon": { "$last": "$geo.coordinates" }
}
}
];
you can simply use this in the project stage of the pipeline:-
{ $project:{ _id:'$_id', lat: {$arrayElemAt : ['$geo.coordinates',0]}, lon: {$arrayElemAt : ['$geo.coordinates',1]}, } }
if you want to know about the arrayElemAt aggregation operator in more detail then click on the below-given link:-
https://docs.mongodb.com/manual/reference/operator/aggregation/arrayElemAt/
for your more information:-
"All documents must store location data in the same order. If you use latitude and longitude as your coordinate system, always store longitude first. MongoDB’s 2d spherical index operators only recognize [ longitude, latitude] ordering."
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