1

In my collection:

{ "code": xx1
  "valueList": [
                  { "id": "yy1", "name": "name1"},
                  { "id": "yy2", "name": "name2"},
                  { "id": "yy3", "name": "name3"}              
               ]
},
{ "code": xx2
  "valueList": [
                  { "id": "yy4", "name": "name4"},
                  { "id": "yy5", "name": "name5"},
                  { "id": "yy6", "name": "name6"}              
               ]
}

I want to return specific ONE matching subdocument (not an array), like below:

{ "id": "yy3", "name": "name3"}  

I try below code:

findOne({ "code": "xx1",
          "valueList.name": "yy3"
       })
.select({ "valueList.$": 1});

It returns an array instead:

 {
   "valueList": [{ "id": "yy3", "name": "name3" }]
 }

How can I solve this? Thank you

elvin
  • 55
  • 7

1 Answers1

1

You can use below aggregation:

db.col.aggregate([
    { $match: { "valueList.id": "yy3" } },
    { $unwind: "$valueList" },
    { $match: { "valueList.id": "yy3" } },
    { $replaceRoot: { newRoot: "$valueList" } }
])

First $match will filter out all unnecessary documents, then you can use $unwind to get valueList item per document and then $match again to get only the one with yy3 in the last stage you can use $replaceRoot to promote valueList item to the top level.

mickl
  • 48,568
  • 9
  • 60
  • 89
  • It works but is returning an array: [{ "id": "yy3", "name": "name3"} ]. Is it possible it can just return the subdocument itself without the array: { "id": "yy3", "name": "name3"} (note: without the [ ])? It will be perfect then, thank you – elvin Feb 15 '19 at 16:09
  • @elvin, that needs to be handled in your app logic, aggregate and find will always return an array, even if it's one-element array – mickl Feb 15 '19 at 16:15