Search code examples
pythonmongodboperatorspymongoprojection

Pymongo find with a projection operator


I have a nested mongodb database and I am trying to perform a query which find entries and returns only certain fields.

The fields that I want returning are nested

The database looks like this

 {
 'material_type':'solid',
 'performance':10,
 'material': {'isotopes': [ { 'abundance': 0.9,
                              'atomic_number': 6,
                             },
                             { 'abundance': 0.1,
                               'atomic_number': 7,
                             }
                           ]
                },
 },
 {
 'material_type':'solid',
 'performance':9,
 'material': {'isotopes': [ { 'abundance': 0.7,
                                 'atomic_number': 6,
                             },
                             { 'abundance': 0.3,
                                 'atomic_number': 7,
                             }
                           ]
                }
 }

I would like to return the nested abundance field but only if the atomic number is equal to 6.

I have tried performing a projection on the query and currently have something like this in python pymongo

 results = database.find({'material_type':'solid'},
                         {'performance':True,
                          'material.isotopes':True 
                         })

I think that I need a projection operation but can't get them to work in pymongo. Any ideas what the pymongo database.find operation should be to return the below fields and values?

  performance , abundance 
  10              0.9
  9               0.7

Solution

  • When using a projection you need to use either 1 or 0 and not True or False respectively.

    Try this:

    find( {'material_type':'solid', 
          'material.isotopes.atomic_number' : {'$eq': 6 } 
          },
          {'_id' : 0, 'performance' : 1,  
          'material.isotopes.atomic_number.$' : 1 } )
    

    Returns:

    {
        "performance" : 10.0,
        "material" : {
            "isotopes" : [ 
                {
                    "abundance" : 0.9,
                    "atomic_number" : 6.0
                }
            ]
        }
    }
    
    /* 2 */
    {
        "performance" : 9.0,
        "material" : {
            "isotopes" : [ 
                {
                    "abundance" : 0.7,
                    "atomic_number" : 6.0
                }
            ]
        }
    }
    

    You use $ in the projection when you only need one particular array element in selected documents. You could of tried $elemMatch if your array wasen't nested.

    You could then put the results into a list and then select the two elements you want to print:

    results = list( db.collection_name.find(
              {'material_type':'solid',  
              'material.isotopes.atomic_number' : {'$eq': 6 }},
              {'performance':1, 
               'material.isotopes.atomic_number.$':1 }
              ))
    

    I'm running pymongo 3.6.0 and mongodb v3.6