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
Related
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);
I am making an MEAN stack app and use Mongoose alongside Mongo. I am struggling with organizing my objects in database. All works as expected but I have a feeling that the way I am doing things is wrong, but can't seem to find any resources on the topic that could help me, thus I hope somebody with some experience can share it with me.
I use Mongoose to create several schemas, and there is one dilemma I am facing, concerning nested objects in MongoDB.
Let's say I have a model that looks like that:
ParentSchema:{
property1:String,
children:[{}]
}
So, property1 is just some string, 'children' is an array that will contain objects of type 'Child' with some other properties, but also another array (f.ex. 'grandchildren:[{]} ), this time with another type of objects (Grandchild).
Child and Grandchild have no schemas and do not exist outside of the Parent, and will most likely be unique to each instance of Parent, so two Parents would not be sharing a Child object.
In my app, I am able to use urls such as '/parent/:id1/Child/:id2/Grandchild/:id3', where 'id1' is an actual id of Parent that Mongo generates, while 'id2' is an index of Child object instance stored in Parents array. The same goes for instances of Grandchildren stored inside Child object.
I was thinking that maybe having separate schemas for all 3 objects, and just saving references to objects is the way to go, like this:
ParentSchema:{
prop1:String,
children:[{type:ObjectId, ref:'Child'}]
}
ChildSchema:{
prop1:String,
granchildren:[{type : ObjectId, ref: 'Grandchild'}]
}
GrandChildSchema:{
prop1:String,
prop2:String
}
..but was unsure, as for me it implies that Child and GrandChild instances would be shared between different parents, however it seems easier to work with.
To sum up, I would like to know is:
which approach should I choose and why: first, second or maybe some other that I do not know about yet.
If I were to choose the second approach, should I create a separate API route for each of the objects?
How would I go about creating then? My wish is for the process to look like so:
Start creating Parent -> start creating first Child -> create some Grandchildren ->
finish creating Child -> start creating second Child -> ... -> finish creating Parent.
I apologize if the question is somehow weird, I will try to clarify as best as I can if required.
I would go with the second approach for a couple of reasons:
Schemas have better readability in my opinion.
They allow for data validation which you lack in the first approach.
Please note the answer below is primarily opinion based.
For the API design:
I think its really up to you as to which paths to expose to the consumer, since you've stated Child and Grandchild do not have the right to exist without a parent - I think your routes are fine as they are.
And finally - your process for creating these entities look fine to me. I would do the same thing myself.
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.
I'm trying to find all object which have no parent (i.e. which were created with parent=None).
Using M.all().filter("parent = ", None).fetch(100) doesn't bring any results, even though some objects certainly do have no parent.
What am I doing wrong?
There's no way to query specifically for root entities. You need to either use external information (eg, no entity of type Foo has parents), or add a property that indicates if an entity is a root entity or not.
You don't use filter() to query for an ancestor. Try instead:
M.all().ancestor(None).fetch(100)
Edit: hmm, that won't work apparently (I'd swear I had done this somewhere). So you'd need to save an extra property as a flag for root entities.
Can anyone tell or define more what is "ancestor" and give an example on it and also what it is for? I just can't grasp what it really is.
Reference: http://code.google.com/appengine/docs/python/datastore/queryclass.html#Query_ancestor
Thanks.
Transactions in GAE only exist within ancestor-descendant groups. Equivalently, quoting the docs at the URL I just gave,
All datastore operations in a
transaction must operate on entities
in the same entity group
and an "entity group", per this page in the docs, are defined by:
When the application creates an
entity, it can assign another entity
as the parent of the new entity, using
the parent argument in the Model
constructor. Assigning a parent to a
new entity puts the new entity in the
same entity group as the parent
entity.
"Ancestor" is just the transitive closure of "parent" -- i.e., given an entity, its ancestors are, its parent, its parent's parent, and so forth.