Reference property for parent/ancestor relation? - google-app-engine

What is the best practice when it comes to reference properties for parent/ancestor relations in AppEngine? Should I add a reference property pointing from the parent to the child to make it easy to access the child in the parent, or should I just "suck it up" and do a ancestor query from the parent to get it's children.

If there is only one child, you could use a known key_name so you can directly fetch the child (since you know the parent's key). This can be useful because any time you know the parent's key name or id you can easily fetch the child directly.
child_key = db.Key.from_path('ChildKind', 'knownname', parent=parent_key)
child = db.get(child_key)
If there are multiple children you could potentially store a list of keys (it can be unindexed) on the parent, or use an ancestor query. I would say it depends how your data is updated, reported on (presented), and the volume of data. In other words it depends on the needs of your application.

Related

Objectify - get all of a type regardless of parent

I have child entities with #Parent key ref in them.
When I give the parent key, I am able to get the child entity like this:
OfyService.ofy()
.load()
.type(Child.class)
.parent(parentKey)
.id(childId).now();
I tried to access the child entity directly without giving the parent key, but that doesn't work (returns null):
OfyService.ofy()
.load()
.type(Child.class)
.id(childId).now();
Is there another way to query one or all instances of a kind regardless of parent?
For example, _ah/admin is able to list all the entities of a Kind regardless of the parent.
Iterable<Child> children = ofy().load().type(Child.class);

Component to edit part of parent's state

Ok I am studying React.JS now. Consider the following situation. There is a root component holding the model as state. One of its children is a complex control responsible for editing part of the model. There are some rules: some user's actions modify the part in one way (to be specific, sets a list to contain exactly one clicked item), other actions modify it in other way (like, simply add that item to the list). Those rules, of course, are not imposed by business logics, it's just the way I designed the particular child component. Now I have to decide how to connect the child's UI elements to the model and vice versa.
1) I can make the child stateless. Make it accept the current model state as props, render its UI according to that props, and upon click, send the parent an event (via some callback in props) "hey I've been clicked this way". The parent can examine the event and either apply setState(model=>replace_list_single_entry(model,event.id)), or setState(model=>add_entry_to_list(model,event.id)).
Drawback: the parent has to know much about logic specific to a component implementation, while actually I should be able to switch to another component with another implementation. So much for encapsulation, component-driven design, and low coupling.
2) I could make the component calculate a new state for parent (at least in some form, maybe not exactly one which is in the model), send it to some props.onChange, and then the parent could simply setState to accomodate this calculated state.
The severe drawback as I see it is, since setState is asynchronous and can be batched, an event loss might occur. Look, the child interprets the user's actions as "add ID1 to list", takes its props.list, makes another list of it and of the ID1, and sends that list to a parent, which makes setState; while that setState is still pending, the user makes another click to add yet another ID2, but the child's props.list is still the same, so the child sends the parent a new calculated list containing ID2 but not ID1. The parent calls setState with this new list and voila, eventually ID1 is lost from the list.
3) I could send the parent not the state calculated from my props, but state calculator. The parent applies this calculator to some "props" object, which it populates from the current state in the same way as if to pass to children's props. (I mean, this may be simply some property from the model, but may be something pre-processed) The resulting "props" are then re-integrated into the model.
Drawback: it looks overcomplexified. But maybe that's the way to go, actually.
4) I could make the component stateful, have its own state describing its UI controls, and after each set state completion, send the updated state to the parent. This however is no different from approach (2) in sense of drawbacks, and adds some more concerns - admittedly, quite solveable, - like, keeping internal state eventually-consistent with parent's state.
So, what is the proper way to do the trick?
It really does not make any sense to me.
I mean, the pattern "<Child onChange="{event=>this.setState(event.data)}>"> (or something similar) is SO common, everyone rushes to suggest it when some newbie asks "how do I affect parent's state in a child?". But it's enigmatic how everyone is silent when I say "this approach has major drawbacks, how do I avoid them?" How do they people write their code, then?
OK the only solution, given that no one experienced user could give me an exhaustive answer, seems to be "don't make a parent's state dependent on children, make components only responsible for non-overlapping sections of the model, instead of mapping children to a subsection of what's already mapped to a parent".
Even despite such an approach is actually not a decomposition.

How to ensure that my entity will never be an orphan?

Sometimes, you make an entity kind that is supposed to exist in another entity. However, if it turns into an orphan, it will have no reason to exist in the datastore anymore.
What happens to child datastore objects after deleting the ancestor?
According to the link above,
"Child entities do not get deleted when the ancestor is deleted"
"child_entity.key.parent().get() will return None."
If I delete the ancestor, the child will have no parent, making it an orphan.
This is a problem, as there is no reason for it to stay in the datastore anymore.
Is there any way to ensure this never happens in the database?
Possible solutions I can think of are:
Routinely run macros to delete orphans
Try to clean the code/weed out bugs that may cause my child to turn into an orphan
However, the I'm hoping for a more programmatically correct solution like an attribute or property that can be set to ensure me that the parent(key) will never point an entity that doesn't exist. (aka automatically delete the entity when ancestors are deleted)
Is there?
If yes, what is it?
If no, why not?
A child entity can never become a root entity, since it continues to have the same parent key, even if the parent was deleted (or never existed).
An entity's parent key can not be changed during the entity's lifetime since the parent key is embedded in the entity's key.
As for automatically removing an entity's descendents when the entity is deleted - there is no such way. But it can be achieved programatically, see How to delete an entity including all children.

Hierarchical queries for Parent-Child entities in App Engine

Is it possible to query Parent + Child entities in a single query pass?
This would require a JOIN in SQL, but in the underlying BigTable the keys are sequential, so it should theoretically by possible to scan Parent and Child entities in a single pass. For example:
Parent-1
Parent-1-Child-A
Parent-1-Child-B
Parent-1-Child-C
Parent-2
Parent-2-Child-D
Parent-3
Parent-3-Child-E
Ancestor queries limit the scope to a single Parent. What I'm looking for is Query by key range that isn't limited to a single Kind.
Something like that doesn't exist by default.
One way I have addressed this is by having each entity store all of it's possible paths as a repeated property, including itself if you want it to be returned in the query the way ancestor queries do. In addition store the path of the immediate parent.
ie (I will include an example with more than 2 levels)
Parent-1
paths = ['Parent-1']
parent = []
Parent-1-Child-A
paths = ['Parent-1','Parent-1/Child-A']
parent = ['Parent-1']
Parent-1-Child-C
paths = ['Parent-1','Parent-1/Child-C']
parent = ['Parent-1']
Parent-1-Child-C-Child-F
paths = ['Parent-1','Parent-1/Child-C','Parent-1/Child-C/Child-F' ]
parent = ['Parent-1/Child-C']
Parent-1-Child-C-Child-E
paths = ['Parent-1','Parent-1/Child-C','Parent-1/Child-C/Child-E' ]
parent = ['Parent-1/Child-C']
This way you can query for any key range and limit the depth to immediate children) Ancestor queries have no means of limiting depth.
This would require you to use PolyModel (you haven't said if your using python or java - I don't know if java has a PolyModel analog). So Parent and Child would inherit from Node which would be based on PolyModel
class Node(ndb.PolyModel):
pass
class Parent(Node):
pass
class Child(Node):
pass
Though you may not need different classes for parent and child.
One thing to note, if you use ancestors/parents in the key you can not re-arrange your heirarchies without completely copying/re-writing all of the children

Is it possible to create references in Google App Engine?

Let's say I have a datastore that contains mother, father, and child objects. Inside the Mother and Father objects I have a field called child which stores a reference to their child. Is it possible to reference this child from both mother and father without creating duplicate child instances for each (in the style of OOP). Is this how databases work at all?
Yes, you can use the db.ReferenceProperty to do exactly that.
A reference property simply stores the unique key of the entity it references. So the mother and father entities could each contain a copy of the key corresponding to their child like this:
class Child(db.Model):
... # child properties
class Father(db.Model):
child = db.ReferenceProperty(Child)
...
class Mother(db.Model):
child = db.ReferenceProperty(Child)
...

Resources