Question

The function below searches a collection with a subitem projects. If there is a subitem with isManager set to 1 it should return True otherwise it will always return False.

def isMasterProject(self, pid, uid):
  masterProjects = False
  proj = self.collection.find({ "_id": uid, "projects": { '$elemMatch': { "projectId": _byid(pid), "isManager": 1 } } })
  for value in proj:
    if str(value['projects']['projectId']) == pid:
      if value['projects']['isManager'] == 1:
        masterProjects = True
  return masterProjects

_byid is equivalent to ObjectId

It always seem to return False. Here's an example of a collection.

{
  "_id" : ObjectId("52cf683306bcfc7be96a4d89"),
  "firstName" : "Test",
  "lastName" : "User",
  "projects" : [
    {
      "projectId" : ObjectId("514f593c06bcfc1e96f619be"),
      "isManager" : 0
    },
    {
      "projectId" : ObjectId("511e3ed0909706a6a188953d"),
      "isManager" : 1
    },
    {
      "projectId" : ObjectId("51803baf06bcfc149116bf62"),
      "isManager" : 1
    },
    {
      "projectId" : ObjectId("514362bf121f92fb6867e58f"),
      "isManager" : 1
    }
  ],
  "user" : "test.user@example.com",
  "userType" : "Basic"
}

Would it be simpler to check for an empty cursor and if so how would I do that?

Was it helpful?

Solution

How about:

obj = next(proj, None)
if obj:

$elemMatch should only return results if the criteria given match a document so you should only return a cursor from find where your criteria are true.

Since you are using _id in the query and only ever expect to get one result, why not use findOne and shortcut one step.

Another gotcha for the new initiates, be aware you are returning the whole document here and not some representation with only the matching element of the array. Things that did not match will still be there, and then expecting different results by iterating over these will lead you to grief.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top