MongoDB flatten result list of certains fields in list of dicts

Lest say I have data like

[{
  _id: 1, 
  items: [
    {a: 1, b: 2},
    {a: 2, b: 2},
    {a: 15, b: 7}
  ]
}, {
  _id: 2, 
  items: [
    {a: 15, b: 9},
    {a: 15, b: 9},
    {a: 41, b: 9}
  ]
}]

I want to ask for items.a elements, so i result I will have

[[
  1,
  2,
  15
], [
  15,
  15,
  41
]]

I know that

db.collection.find({}, {"items.a": true, "_id": false})

will return

[{
  items: [
    {a: 1},
    {a: 2},
    {a: 15}
  ]
}, {
  items: [
    {a: 15},
    {a: 15},
    {a: 41}
  ]
}]

And that is not what I am looking for.

And is it worth to calculate it in MongoDB or I can calculate it in Python?

Edit: And what if I want to check it by for example: return every list that contains items.a: 1

so the result should be in that case

[[
  1,
  2,
  15
]]

Upvotes: 2

Views: 554

Answers (1)

chridam
chridam

Reputation: 103455

You can run the following aggregation pipeline which uses the $map operator within a $group pipeline to create the arrays of values for mapped elements of the embedded document a field:

db.collection.aggregate([
    {
        "$group": {
            "_id": null,
            "elements": {
                "$push": {
                    "$map": {
                        "input": "$items",
                        "as": "item",
                        "in": "$$item.a"
                    }
                }
            }
        } 
    }
])

Sample Output:

{
    "_id" : null,
    "elements" : [ 
        [ 
            1, 
            2, 
            15
        ], 
        [ 
            15, 
            15, 
            41
        ]
    ]
}

If you you only want to return all items where the one of the elements has a value of 1, you would need to place a $match filter before the grouping, as in the following:

db.collection.aggregate([
    { "$match": { "items.a": 1 } },
    {
        "$group": {
            "_id": null,
            "elements": {
                "$push": {
                    "$map": {
                        "input": "$items",
                        "as": "item",
                        "in": "$$item.a"
                    }
                }
            }
        } 
    }
])

Sample Output

{
    "_id" : null,
    "elements" : [ 
        [ 
            1, 
            2, 
            15
        ]
    ]
}

Upvotes: 1

Related Questions