Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check for existence of multiple fields in MongoDB document

I am trying to query a database collection that holds documents of processes for those documents that have specific fields. For simplicity imagine the following general document schema:

{
    "timestamp": ISODate("..."),
    "result1": "pass",
    "result2": "fail"
}

Now, when a process is started a new document is inserted with only the timestamp. When that process reaches certain stages the fields result1 and result2 are added over time. Some processes however do not reach the stages 1 or 2 and therefore have no result fields.

I would like to query the database to retrieve only those documents, which have BOTH result1 and result2.

I am aware of the $exists operator, but as far as I can tell this only works for one field at a time, i.e. db.coll.find({"result1": {$exists: true}}). The $exists operator cannot be used as a top level operator. E.g. this does not work:

db.coll.find({"$exists": {"result1": true, "result2": true}})

To check for both results I would need:

db.coll.find({"result1": {"$exists": true}, "result2": {"$exists": true}})

Now that already becomes tedious for more than one variable.

Is there a better way to do this? (Also, I am doing this in Python, so if there is a solution for just the pymongo driver that would make me happy already.)

like image 300
pnd Avatar asked Oct 19 '22 08:10

pnd


1 Answers

I don't know about better, but you can always process with JavaScript via $where:

jsStr = """var doc = this;
           return ['result1','result2','result3']
           .every(function(key) { 
               return doc.hasOwnProperty(key) 
           });"""

coll.find({ "$where": jsStr })

But you are going to have to specify an array of "keys" to check for somewhere.

If you think you have a lot of keys to type out, then why not just "build" your query expression:

whitelist = [ "result1", "result2", "result3" ]
query = {}

for key in whitelist:
    query[key] = { "$exists": True }

coll.find(query)

That saves a bit of typing and since all MongoDB queries are just data structures anyway then using basic data manipulation to build queries makes sense.

like image 149
Blakes Seven Avatar answered Oct 22 '22 00:10

Blakes Seven