9

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.

0

2 Answers 2

6

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" }
        }
    }
];
Sign up to request clarification or add additional context in comments.

Comments

1

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 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."

Comments

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.