curiousone
curiousone

Reputation: 33

Query to convert an array to a map of documents with n attributes

I'm converting an array to a map in mongo.

  "items":[  
    {  
      "id":"AB-02",
      "qty":2
    },
    {  
      "id":"AB-03",
      "qty":0
    },
    {  
      "id":"AB-03",
      "qty":9
    }
  ]

becomes

 "items":{  
    "AB-02":{  
      "id":"AB-02",
      "qty":2
    },
    "AB-03":{  
      "id":"AB-03",
      "qty":0
    },
    "AB-04":{  
      "id":"AB-03",
      "qty":9
    }
  }

in the array version, it's quite easy to query based on how many elements inside items, but how do I do that with the latter format of items? as in, to query those documents whose items has lets say 7 elements?

Upvotes: 3

Views: 1968

Answers (1)

chridam
chridam

Reputation: 103365

From MongoDB 3.4.4 and above, you can use the $arrayToObject operator that transforms an array into a single document and the array should be a list of documents that contains two fields, k and v where:

The k field contains the field name.

The v field contains the value of the field.

So you would need to create a pipeline that first transforms items array from

"items":[  
    {  
      "id":"AB-02",
      "qty":2
    },
    {  
      "id":"AB-03",
      "qty":0
    },
    {  
      "id":"AB-03",
      "qty":9
    }
]

to

"items" : [ 
    {
        "k" : "AB-02",
        "v" : {
            "id" : "AB-02",
            "qty" : 2.0
        }
    }, 
    {
        "k" : "AB-03",
        "v" : {
            "id" : "AB-03",
            "qty" : 0.0
        }
    }, 
    {
        "k" : "AB-03",
        "v" : {
            "id" : "AB-03",
            "qty" : 9.0
        }
    }
]

$map correctly does that with the expression

"$map": {
    "input": "$items",
    "as": "item",
    "in": {
        "k": "$$item.id",
        "v": "$$item"
    }                            
}

So your final pipeline can wrap all the above operators into a single stage with $addFields as:

db.collection.aggregate([
    {
        "$addFields": {
            "items": {
                "$arrayToObject": {
                    "$map": {
                        "input": "$items",
                        "as": "item",
                        "in": {
                            "k": "$$item.id",
                            "v": "$$item"
                        }                            
                    }
                }
            }
        }
    }
])

Upvotes: 4

Related Questions