简体   繁体   中英

find/get sub-array from an array of sub-document in MongoDB

I have documents in a collection in following format :

{"hourNo":"0","errorSegments":[

{
 "errorSegmentId" : "1019",
 "errorCode" : "401"
},
{
 "errorSegmentId" : "1022",
 "errorCode" : "402" 
},
{
     "errorSegmentId" : "1010",
     "errorCode" : "405"
    }

]}

{"hourNo":"1","errorSegments":[

{
 "errorSegmentId" : "1011",
 "errorCode" : "405"
},
{
 "errorSegmentId" : "1055",
 "errorCode" : "405"
},

{
 "errorSegmentId" : "1033",
 "errorCode" : "405"
},
{
 "errorSegmentId" : "1042",
 "errorCode" : "408" 
}

]}

First criteria to match is the hourNo , as there will be other documents with different hour numbers.

The final output required is sub-array of the sub-document that has "errorSegmentId", "errorCode" that matches the criteria of certain errorCode .

For example :

Getting all the errorSegments that are in hour 1 that have errorCode 405 .

So the output would be :

{
 "errorSegmentId" : "1011",
 "errorCode" : "405"
},
{
 "errorSegmentId" : "1055",
 "errorCode" : "405"
},

{
 "errorSegmentId" : "1033",
 "errorCode" : "405"
}

=============================================================

I have tried few aggregation operations , but i am not able to get desired result .

TIA.

You can use below aggregation in 3.4.

$match to only filters documents where there exists errorSegments array with at least one errorCode matching input error code.

$filter the errorSegments to only contain errorSegment matching from input error code followed by $unwind and $replaceRoot to promote the matching values to the top.

db.col.aggregate([
  {"$match":{"hourNo":"1","errorSegments.errorCode":"405"}},
  {"$project":{
    "errorSegments":{
      "$filter":{
        "input":"$errorSegments",
        "as":"e",
        "cond":{"$eq":["$$e.errorCode","405"]}
      }
    }
  }},
  {"$unwind":"$errorSegments"},
  {"$replaceRoot": {"newRoot":"$errorSegments"}}
])

In an aggregation pipeline match all documents where hourNo is 0 .

Then unwind errorSegments array into individual documents.

Query the resulting documents for documents where errorSegments.errorCode is 405 .

Lastly, replaceRoot .

db.test.aggregate([
    {$match: {"hourNo": "0"}},
    {$unwind: "$errorSegments"}, 
    {$match: {"errorSegments.errorCode": "405"}}, 
    {$replaceRoot: {newRoot: "$errorSegments"}}
])

Sample query results:

{ "errorSegmentId" : "1011", "errorCode" : "405" }
{ "errorSegmentId" : "1055", "errorCode" : "405" }
{ "errorSegmentId" : "1033", "errorCode" : "405" }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM