Reputation: 67
I am trying to create hierarchical queries on the App Engine.
My datastore have parents and children. Each parent has children. Imagine that I have to find children. I have a condition on the parent and an other on the children for example, imagine a real family datastore, my conditions are: I want all children that are a boy from parent who are 35 years old or more.
The query I have for now is something like:
P = Parent.query(Parent.age >= 35)
for p in P:
C = Children.query(gender == "boy", ancestor = p.key)
for c in C:
-> here I print information on the children
But the query is very slow with a lot of parent and children to test. I want to avoid iteration like for etc. because I think it take a long time because of that! What is the best practice to have his kind of query but quickly?
I have also brothers for the children and I can make queries, for example if I want all children that have parent that are more that 35 yers old and a sister named "Sisi", I will have (each children have his brothers on the value "brother"):
P = Parent.query(Parent.age >= 35)
for p in P:
C = Children.query(gender == "girl", name == "Sisi", ancestor = p.key)
for c in C:
C1 = Children.query(gender == "boy", brother == c.key, ancestor = p.key)
for c1 in C1:
->Here I print information about the children
In fact this example (family example) good for my project but it give an idea of the problem I have
Upvotes: 2
Views: 567
Reputation: 693
How I've been able to do this before is to store the keys in a separate lookup entity. This goes along the key-value store premise that duplicate info is sometimes necessary for faster lookups. For example:
ParentChildLookup
- parent_key = ndb.KeyProperty()
- child_key = ndb.KeyProperty()
You could even add a third dimension of you are getting grandchildren:
ParentChildLookup
- parent_key = ndb.KeyProperty()
- child_key = ndb.KeyProperty()
- grandchildren_key = ndb.KeyProperty()
If you wanted to look everything up in a single query, you can add the repeated clause to make children and grandchildren a list:
ParentChildLookup
- parent_key = ndb.KeyProperty()
- child_key = ndb.KeyProperty(repeated=True)
- grandchildren_key = ndb.KeyProperty(repeated=True)
You then need to insert/update these lookup values anytime there's a change in relationships. The benefit of this is that you can avoid a lot of queries, specifically nested or multi-property queries. If you don't like this approach, I would recommend taking a look at the "Relationship Model" explanation here: https://cloud.google.com/appengine/articles/modeling. You can store the relationships between many-to-many objects without the need to store them all in the same entity.
Upvotes: 1