Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MongoDB project into an array

I have array of objects (nested), and I want to pull a couple of the elements from those nested objects, and return these fields in an array. Below is my document structure (mocked it from original data)

"detailLine": [
    {
        "name": "first",
        "value": {
            "lineNumber": 1,
            "subLineCode": " ",
            "detailLineCharges": {
                "allowedAmount": {
                    "amount": "11111",
                    "reasonCode": “aaaah”
                }
            }
        }
    },
    {
        "name": "first",
        "value": {
            "detailLineCharges": {
                "allowedAmount": {
                    "amount": "22222",
                    "reasonCode": “BBBB”
                }
            }
        }
    }
]

I would like to see my results something like this

details: [
  {
    amount:”11111”,
    reasonCode : “aaaah”
  },
  {
    amount : “22222”,
    reasonCode : “BBBB”
  }
]

I tried

 db.collection.aggregate([
   {
     $match: {
       _id: "123456"
     }
   }, 
   {
     $project: {
       details: {
         $push {
           amount: "$detailLine.value.detailLineCharges.allowedAmount.amount",
           reasoncode: "$detailLine.value.detailLineCharges.allowedAmount.reasonCode"
         }
       }
     }
   }
])

but I am getting this error

Error: command failed: { "ok" : 0, "errmsg" : "invalid operator '$push'", "code" : 15999 } : aggregate failed :

I want to use $project because I am using it to pull too many other fields so that is why I did not try $group for this one particular scenario.

Can anyone help how to get those two fields in an Array?

like image 576
JBone Avatar asked Jun 30 '16 17:06

JBone


2 Answers

Well, all you need is $project your documents and "reshape" them using the $map operator.

db.coll.aggregate( 
    [ 
        { "$match": { "_id": "123456" } },
        { "$project": { 
            "detailLine": { 
                "$map": { 
                    "input": "$detailLine", 
                    "as": "dline", 
                    "in": { 
                        "amount": "$$dline.value.detailLineCharges.allowedAmount.amount", 
                        "reasonCode": "$$dline.value.detailLineCharges.allowedAmount.reasonCode" 
                    } 
                } 
           } 
        }} 
    ]
)
like image 106
styvane Avatar answered Oct 14 '22 09:10

styvane


With the following pipeline it gives you the desired result, although I use $group. Of course you may need to adjust the group identifier.

db.getCollection('yourCollection').aggregate([
  {     
      $unwind: {
          path: "$detailLine"
      }
  },
  {
      $project: {
          allowedAmount: "$detailLine.value.detailLineCharges.allowedAmount"
      }
  },
  {
      $group: {
          _id: "x",
          details: {
              $push: "$allowedAmount"
          }
      }
  }
])

Result

{
    "_id" : "x",
    "details" : [ 
        {
            "amount" : "11111",
            "reasonCode" : "aaaah"
        }, 
        {
            "amount" : "22222",
            "reasonCode" : "BBBB"
        }
    ]
}
like image 25
DAXaholic Avatar answered Oct 14 '22 09:10

DAXaholic