0

I am trying to query something in EmbeddedDocumentFieldList field, and I want use or operate into conditions. schema as blew:

class EmbeddedDoc(EmbeddedDocument):
     name = StringField()

class ParentDoc(Document):
     name = StringField():
     children = EmbeddedDocumentFieldList(EmbeddedDoc)

then I want to get something named "a" or "b" children of the ParentDoc, I tried use Q function, but program threw a exception said "filter method taken 1 params but it were given 2". any other way guys? Thanks

Scott
  • 1
  • 3

1 Answers1

0

I have no clue as to what your "Q" function is doing, but I'm going to show you how I query embedded documents. (EDITED: I see what you're talking about the "Q" now. Added to my answer down below)

Looking at your models~

class EmbeddedDoc(EmbeddedDocument):
    name = StringField()

    def to_json(self):
        return {
            "name": self.name 
        }


class ParentDoc(Document):
    name = StringField()
    children = EmbeddedDocumentFieldList(EmbeddedDoc)

    def to_json(self):
        return {
            "_id": str(self.pk),
            "name": self.name,
            "children": [child.to_json() for child in self.children]
        }

I override the to_json() method to make it more human readable. That part is optional, but I recommend it. I would do somethin like this in my method~

pdoc = ParentDoc.objects(pk=some_ID_variable)
if pdoc:
    pdoc = pdoc.get(pk=some_ID_variable)
    if pdoc.children.filter(name=some_name_variable):
        child = pdoc.children.get(name=some_name_variable)
        return child.to_json()
    return {"message": "Child with that name not found"}
return {"message": "Parent with ID not found"}

What's going on? First I query to see if the ParentDoc exists. If it exists, get the ParentDoc object from the queryset. Query the object's embedded objects by name using filter, since embedded objects don't have primary keys. If it exists return the embedded object in json format.

According to the advanced queries section Mongoengine User guide, to use an or operator, I'll need to use the or bitwise operator "|" along with a Q class. So I'd add this ~

from mongoengine.queryset.visitor import Q

and change the above filter to something like~

children = []
cdocs = pdoc.children.filter(Q(someParam=someValue) | Q(anotherParam=anotherValue))
children.append(cdoc.tojson() for cdoc in cdocs)
return {"Children": children}

I've not used this though. Hope it works for ya!

Joseph Vargas
  • 772
  • 5
  • 17
  • Thank you for your explaining, and it's very helpful for me. but I have another question, How do I use or_operation to query the children field, like name is 'John' or 'Tom', both are my need. – Scott Jul 13 '18 at 03:09
  • I've never used the or_ operator. I didn't even know it existed. I would probably just programatically do it in plain python. Just filter the object you already have with an "or" in your "if" statement, or an "if/else" statement or something like that. – Joseph Vargas Jul 13 '18 at 23:31
  • If my above suggestion isn't what you are looking for, then I think your answer is to use raw pymongo queries . – Joseph Vargas Jul 13 '18 at 23:42
  • You're right, I can't find any answer from internet, I think I need to use raw pymongo queries, anyway thanks. – Scott Jul 17 '18 at 10:43
  • Hey Scott, I just found [this answered question on here](https://stackoverflow.com/questions/8189702/mongodb-using-an-or-clause-in-mongoengine). I have also found [this section in the User guide](http://docs.mongoengine.org/guide/querying.html#advanced-queries). I don't have this use case so not sure if it works though. – Joseph Vargas Jul 18 '18 at 09:58
  • Edited my answer for anyone else who stumbles on this post. Everything is same as before, but added some additional lines based on what I read in my previous comment. – Joseph Vargas Jul 18 '18 at 10:12
  • Thank you for your concern, But I have tried it and it doesn't work on EmbeddedDocumentFieldList instance, it just work on query of Document instance, But still thanks, Joseph – Scott Jul 19 '18 at 10:55