Home > Blockchain >  Find data in mongoDB with Python by filtering through a list of dictionaries
Find data in mongoDB with Python by filtering through a list of dictionaries

Time:11-17

I have a list similar to this with the unique keys of a table and I need to retrieve all the records of a table that have these pk:

lista_pks = [
 {'pers_id': '00002', 'cod': '01'},
 {'pers_id': '00003', 'cod': '01'},
 {'pers_id': '00014', 'cod': '01'},
 {'pers_id': '00015', 'cod': '01'},
 {'pers_id': '00017', 'cod': '01'},
 {'pers_id': '00018', 'cod': '01'},
 {'pers_id': '00019', 'cod': '01'}
]


columns = {"_id":0,"pers_id":1,"cod":1, "doc":1}
database["collection_2"].find(lista_pks ,columns)

Expected:

|cod | pers_id | doc|
---------------------
|01  | 00002   | DNI|
|01  | 00003   | DNI|
|01  | 00014   | DNI|
|01  | 00015   | DNI|
|01  | 00017   | DNI|
|01  | 00018   | DNI|
|01  | 00019   | DNI|


Until now I only had to filter by concrete values but now I need to replicate something like this but I can't see how I could do it:

where (pers_id = '00000002' and cod = '0001') or (pers_id = '00000003' and cod = '0001')
or (pers_id = '00000014' and cod = '0001') or (pers_id = '00000015' and cod = '0001')
or (pers_id = '00000017' and cod = '0001') or (pers_id = '00000018' and cod = '0001')
or (pers_id = '00000019' and cod = '0001') 

Edit: I create a function like this:

or_cond = {}
and_cond= list()
for dict_i in lista_pks:
    query_aux = {}
    query_aux['$and'] = [dict_i ]
    and_cond.append(query_aux)

or_cond['$or'] = and_cond

Output:
{'$or': [{'$and': [{'pers_id': '00002', 'cod': '01'}]}, {'$and': [{'pers_id': '00003', 'cod': '01'}]}, {'$and': [{'pers_id': '00014', 'cod': '01'}]}, {'$and': [{'pers_id': '00015', 'cod': '01'}]}, {'$and': [{'pers_id': '00017', 'cod': '01'}]}, {'$and': [{'pers_id': '00018', 'cod': '01'}]}, {'$and': [{'pers_id': '00019', 'cod': '01'}]}]}

It works but I don't know if this solution is the best

CodePudding user response:

If you are using pymongo

result = collection.aggregate([
{
    "$match": {
        "pers_id" : {
            "$in": ["00000017", "00000016"... ]
        },
        "cod": {
             "$in": ["0001"]
        }
    }
}
])

you can also use find instead of aggregate

CodePudding user response:

Filters in MongoDB are anded by default, so you can simplify your query to:

db.mycollection.find({'$or': [{'pers_id': '00002', 'cod': '01'},
                              {'pers_id': '00003', 'cod': '01'}, 
                              {'pers_id': '00014', 'cod': '01'},
                              { ... <etc> ...}]})

or better still:

db.mycollection.find({'$or': lista_pks})
  • Related