devcodes
devcodes

Reputation: 1088

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.

Upvotes: 0

Views: 288

Answers (2)

Oluwafemi Sule
Oluwafemi Sule

Reputation: 38992

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

Upvotes: 1

s7vr
s7vr

Reputation: 75994

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"}}
])

Upvotes: 1

Related Questions