4

I have mongo document like this

{
    "_id": "5b14679e592baa493e0bc208",
    "productCode": "ABC",
    "corridors": [
        {
            "countryNameEn": "Sweden",
            "countryNameFr": "Suède",
            "countryCode": "SE",
            "currencyNameEn": "Swedish Krona",
            "currencyNameFr": "Couronne suédoise",
            "currencyCode": "SEK",
            "corridorLimit": "abc"
        },
        {
            "countryNameEn": "USA",
            "countryNameFr": "Suède",
            "countryCode": "US",
            "currencyNameEn": "USA",
            "currencyNameFr": "Couronne suédoise",
            "currencyCode": "USD",
            "corridorLimit": "abc"
        }
    ]
},
{
    "_id": "5b14679e592baa493e0bc208",
    "productCode": "XYZ",
    "corridors": [
        {
            "countryNameEn": "Sweden",
            "countryNameFr": "Suède",
            "countryCode": "SE",
            "currencyNameEn": "Swedish Krona",
            "currencyNameFr": "Couronne suédoise",
            "currencyCode": "SEK",
            "corridorLimit": "abc"
        },
        {
            "countryNameEn": "USA",
            "countryNameFr": "Suède",
            "countryCode": "US",
            "currencyNameEn": "USA",
            "currencyNameFr": "Couronne suédoise",
            "currencyCode": "USD",
            "corridorLimit": "abc"
        }
    ]
}

I want to find document whose productCode is ABC and currencyCode is USD in corridors array. How can I return only the matching object from corridors array like only only object that has USD currencyCode should come in result and not all array.

I tried running this query { productCode: 'ABC', corridors: { $elemMatch: { currencyCode: "USD"}}}. But it gives me the whole array and not the only matched element.

1 Answers1

2

I don't think you can use $elemMatch in $project. Check this

Try the following query:

db.collection.aggregate([
{

    $match : {"productCode" : "ABC"}
}, 
{
    $unwind : "$corridors"
}, 
{
    $match : { "corridors.currencyCode" : "USD"}
}, 
{
    $group : {
              _id : "$productCode", 
              corridors : {$addToSet : "$corridors"}
}
}]);

Outputs:

{
    "_id" : "ABC",
    "corridors" : [ 
        {
            "countryNameEn" : "USA",
            "countryNameFr" : "Suède",
            "countryCode" : "US",
            "currencyNameEn" : "USA",
            "currencyNameFr" : "Couronne suédoise",
            "currencyCode" : "USD",
            "corridorLimit" : "abc"
        }
    ]
}

In the result you'll have _id instead of productCode. If you still want productCode, you can just include $project in the end.

Hope this helps!

Arsen Davtyan
  • 1,891
  • 8
  • 23
  • 40
  • 1
    You "think" wrong then. The [`$elemMatch`](https://docs.mongodb.com/manual/reference/operator/projection/elemMatch/) operator has two forms, being one for query and the other ( linked one ) for projection. The question has been long answered though and it's preferable to use `$filter` for "multiple matches" than `$unwind` anyway, for a whole host of reasons. But a standard `$elemMatch` or [positional `$` operator](https://docs.mongodb.com/manual/reference/operator/projection/positional/) is all that is needed for a "single" matching result. – Neil Lunn Jun 14 '18 at 01:32