Search code examples
pythonmongodb-querypymongo

Possible to query for embedded documents and get only those documents rather than where at least one?


I have a Dataset with an individual athlete_id, season and a list of different events and results the athlete did.

[{'id':'123',
    'season':'2019',
    'event_type1':[
    {'Date':'20 Oct 2019,'Location':'somewhere1','result':'182'},
    {'Date':'20 Oct 2019,'Location':'somewhere2','result':'184'}], 
    'event_type2':[
    {'Date':'20 Oct 2019,'Location':'somewhere1','result':'182'},
    {'Date':'20 Oct 2019,'Location':'somewhere2','result':'184'}]
]

Thanks to stackoverflow and documentation I came so far to get all documents with at least one time somewhere1 in event_type1.

query = {
    '$and': [
        {'season': 2019},
        {'event_type1':{ '$elemMatch' : {'Location':'somewhere1'}}}
        ]
    }
db.col.find(query)

However, I want to get event_type1 and somewhere1 results only.

At my current knowledge level I would fall back to loop over the retrieved dictionaries, because I did not find a smarter way in the documentation yet.

Question: Is it possible to retrieve only the required dicts rather than where at least one exists?

Further information, if required: In my use case the event_types contain spaces and are not the same for all athletes. Probably because of the spaces I did not get an $unwind approach to run.


Solution

  • Here's one way to find the documents you want and project the fields the way you want.

    db.collection.find({
      "season": "2019",
      "event_type1.Location": "somewhere1"
    },
    {
      "id": 1,
      "season": 1,
      "event_type1": {
        "$filter": {
          "input": "$event_type1",
          "as": "event",
          "cond": {"$eq": ["$$event.Location", "somewhere1"]}
        }
      }
    })
    

    Try it on mongoplayground.net.