Home > Blockchain >  How to get field and values from the nested document and ignore arrays and objects
How to get field and values from the nested document and ignore arrays and objects

Time:01-12

I have the below 2 documents from a post collection. How to get only key value pairs from "post" object. The match condition will be using "post_id".

{
   "_id":"1001",
   "post":{
      "country_name":"India",
      "state_name":"Maharashtra",
      "city_name":"Mumbai",
      "duration":"10",

      "country":[
         {
            "name":"india"   
         }
      ],
      "site":[
         {
            "site_no":"101",
            "code":"Taj",
            "name":"santacruz"
         }
      ]
   },
   "post_id":"abcd123"
}

{
   "_id":"1002",
   "post":{
      "country_name":"India",
      "state_name":"Karnataka",
      "city_name":"Bangalore",
      "duration":"20",

      "country":[
         {
            "name":"india"   
         }
      ],
      "site":[
         {
            "site_no":"201",
            "code":"COLES",
            "name":"Coles Park"
         }
      ]
   },
   "post_id":"abcd234"
}

The expected result is:

"abcd123":{
  "country_name":"India",
  "state_name":"Maharashtra",
  "city_name":"Mumbai",
  "duration":"10"
 }
"abcd234" : {
"country_name":"India",
      "state_name":"Karnataka",
      "city_name":"Bangalore",
      "duration":"20"
}

I'm able to filter for one object, but for the bulk and with good performance, can you help me to solve this.

CodePudding user response:

You can try this aggregate query:

The trick here is to create an object with keys k and v to define the key and value for the next stage.

The key will be post_id and the value the object with desired values.

In this case values has to be dinamically created so you can:

  • Parse $post object to an array, which allows you to filter values inside.
  • $filter that values to not get arrays or objects using $type.
  • Then convert again the array to object using $arrayToObject.

And the last step is to use $replaceRoot so you can get your desired output.

db.collection.aggregate([
  {
    "$project": {
      "k": "$post_id",
      "v": {
        "$arrayToObject": {
          "$filter": {
            "input": { "$objectToArray": "$post" },
            "cond": {
              "$not": [
                {
                  "$in": [
                    { "$type": "$$this.v" },
                    [ "object", "array" ]
                  ]
                }
              ]
            }
          }
        }
      }
    }
  },
  {
    "$replaceRoot": {
      "newRoot": { "$arrayToObject": [ [ {  k: "$k", v: "$v" } ] ] }
    }
  }
])

Example here

  • Related