Searching through Model relationships in Google App Engine? - google-app-engine

I have 2 models:
class Parent (db.Model) :
data = db.StringProperty()
class Child1 (db.Model) :
parent = db.ReferenceProperty(Parent)
childData = db.StringProperty()
class Child2 (db.Model) :
parent = db.ReferenceProperty(Parent)
childData2 = db.StringProperty()
class Child3 (db.Model) :
parent = db.ReferenceProperty(Parent)
childData3 = db.StringProperty()
....
I want a query which can give me a list of all parents which do not have a child yet. How do i do it?
I do not want to maintain an identifier in the Parent model for each of the children as I want to add new child models very often.

The correct way to handle this is to keep a count in your Parent entity of the number of children. Then, you can simply query for Parents that have child count equal to 0.
You don't need to have the child id in the Parent entity; you want to keep a count of the number of children. It is not necessarily important whether the child is of one Model type or another. The purpose of keeping this running count is that it enables you to solve your problem, which is querying for childless Parents. There is no native capability of the datastore or of AppEngine query objects that provides this functionality.
So since this is not supported natively, you have the choice of doing it one of two ways:
1) keep a running count of the number of children, incrementing or decrementing whenever you add or remove a child;
2a) query EVERY child of every type and record unique values of parent.
2b) query all Parent entities and match them up with the unique parent ids from 2a
I'll leave it to you to decide which approach is the correct one.

Related

Best approach to update a field in Parent object if any update is happening on either of the object

I have to 2 object having master-detail relationship. 
I want to update a Status picklist field in Parent object if any update is happening on either of the object (Parent or child).
What will be the best approach?
Hope this helps give you some idea of the various solutions available. I've ordered them by simplest workflow updates to more complex process builders and lastly apex triggers, which resonates the best practice of clicks over code when implementing solutions on salesforce.
You can use a number of strategies here, I'll outline them below from simplest to complex (overkill):
Workflow: You can use two workflow field updates to do this:
- one on the parent object when a record is edited,
then update the status picklist field on the record .
- and another on the child object when a record is edited,
then upon selecting `field to update` as option, you will
be given the parent object and child object as options to
filter fields on, select parent object to filter fields on
then select the status picklist field from parent object.
Process Builder:
You can use process builder to update parent record from child.
Create a process builder flow on child object and update parent
object along with either of the two:
- create a workflow on the parent object to update the status
picklist field when a record is edited only.
- or alternatively to the workflow on the parent object, create
a process builder flow on parent object and update parent object.
Apex Trigger:
Equally you can go to the lengths of writing an apex trigger
upon the parent object `onupdate` trigger and verify if a valid
change was made(meaning the change made to parent was not a
change on the status picklist field), update the the status
picklist field too.

Creating dynamic Parent Child relationship in Vespa

I have a document (document type A) which has multiple (any number of) children documents of the same type (document type B). The following link from vespa documentation talks about the parent-child relationship.
http://docs.vespa.ai/documentation/search-definitions.html#document-references
For this, we have to define a reference type field and then import any field from the referred document. What if I want multiple document references from the parent document. Can't I define something like,
field child_ref type array<reference<doc_type_child>> {
indexing: attribute
}
certainly, I would have the difficulty of importing a certain field as all the child references have the same field.
Let's say the child document type is model and parent document type is car, basically, I want to have a nested document in which I need the capability of querying based on parent and child fields also. Let's say if I search for Mercedes cars with spokes of wheels in range (3,5), the search for Mercedes brand (parent doc field) in parent documents and further I would like to choose models of Mercedes car results (car1, car2, ...) which have wheel spokes (child doc field) from 3 to 5, (car1[model 1, model 4, model 6], car2[model 2, model 3, model 5]). Basically, hits should be of Mercedes brand and in all those hits, internally hits of models which have 3-5 wheel spokes.
The relationship goes from the child document to the parent so no you cannot store child document references in the parent document.
But the example you provide is fully doable with car being the parent (global) document type and model the child, each child document references the parent (car) and can import any field from the parent document type while matching/searching is performed against the child (model) document type and you can search both model document fields and the imported parent car fields. /search/?query=car_brand:mercedes+AND+model_spokes:[3;5]&restrict=model
Where car_brand is an imported field from the parent car in the model document type.

Can different entities of the same kind have different parents in Google ndb at the same time? If yes, how is this useful?

During the declaration of the model class, there are no restrictions for adding the parent key:
class Employee():
name = ndb.StringProperty(required=True)
class Address():
city = ndb.StringProperty(required=True)
class Education():
college = ndb.StringProperty(required=True)
The current way in which we add the ancestor path is during the write to the Datastore as shown below
employee = Employee()
employee.put()
address1 = Address(parent=employee)
So, there is nothing that prevents from one doing:
address1 = Address(parent=employee)
address2 = Address(parent=education)
which sorta feels wierd!
Yes, they can - the parent can literally be an entity of any kind (or None - standalone entities, AKA entity group owners).
You example is exactly one such type of usage.
As for the usability it really depends on the application. If you find it useful, it is :) If not - you're probably not gonna use it.
For example your app might also have entities for businesses or colleges/universities, which would all have at least one Address child entity associated with them.
Side notes:
you should have your classes inherit the ndb.Model class to make their instances ndb entities:
class Address(ndb.Model):
you should pass the parent entity's key in the child creation, not the parent entity itself:
address1 = Address(parent=employee.key)

Get a list of all unique tags used within a set of entities

I've got two models: Group and Item. An Item has a list of tags and belongs to a Group.
class Group(db.Model):
name = db.StringProperty()
class Item(db.Model):
title = db.StringProperty()
tags = db.StringListProperty()
group = db.ReferenceProperty(Group)
So far, typical actions are adding a tag to an Item, removing a tag from an Item, and showing all Items matching a given Group and tag.
What's a good way for getting a list of all unique tags used within a Group?
Ideally I'd like to have a property in Group that reflects the tags used:
class Group(db.Model):
name = db.StringProperty()
aggregated_tags = db.StringListProperty()
It would be even better if this included the number of Items that have this tag.
Permanent consistency is not a requirement, i.e. it is fine if the aggregated list of tags does not match the actual list of tags in use, as long as they become consistent eventually.
Item and Group are not in the same entity group, so I can't have a transaction that updates the Item and the Group at the same time.
The best way to do this is to maintain it yourself. Update the list of tags whenever you add or remove one from an item. You can do this in a task queue task if you want to do it asynchronously.
Alternatively, you could write a mapreduce that you run periodically that recalculates the tag set for every group - in fact, this is pretty much a classic use-case for mapreduce.

Google AppEngine (GAE) - complete object key

I have a list of child entities in my datastore.
I query the datastore to get their id and name to show them in a listbox. (I send the long id)
When the user selects an entity I need to get the entity info.
I'm using this:
Key parentKey = KeyFactory.createKey(Parent.class.getSimpleName(), parentLongKey);
Key childKey = KeyFactory.createKey(parentKey, Child.class.getSimpleName(), childLongKey);
manager.getObjectById(Child.class, childKey);
and it works, but if the child class has it own child class I'll need to create the parent key, the child key and the subchild key???
There is a way to get some id type enough to query the child entity without creating the parents entities???
I tried using the string but has the same problem.
I tried the .toString key version and it has a similar problem
Thx a lot!
Use the stringified version of the whole key, using keyToString and stringToKey.

Resources