I have a model. When I list id of all entries of the model. Some id of them are same. When I create the entries, didn't defined id for them it's assigned automatically. Maybe some of them have a different parents.
So is entry.key.id unique for across all entries of a model? or it's defend on parent of them?
No, it depends on the parent. The path - that is, parent kind, parent ID, child kind, child ID - is unique, but child ID is reused (although not deterministically) across different entity groups.
FYI: Google App Engine Datastore Documentation
http://code.google.com/appengine/docs/python/datastore/entities.html#Kinds_IDs_and_Names
http://code.google.com/appengine/docs/python/datastore/
Related
I use go with app engine and datastore. I have Restaurants and Owners entities. Owner is parent to Restaurant. I show list of restaurants on main web page. When visitor clicks on a restaurant, the profile page(www.../restaurants/:id) will open. I don't have ancestor key at that point. How should I retrieve the restaurant? I could use /restaurants/:key but datastore.key is quite long string.
What is the natural way of doing this? should I use unique restaurant names and query/filter by that?
You can keep your current data model (restaurants child entities of owners). All you need is to add "Owner" variable to a restaurant.
When you retrieve restaurant entity, you can extract owner ID from its key - every key already includes a parent key, if any. In Java it looks like this:
restaurant.setOwner(entity.getParent().getId());
When you need to get/save the restaurant entity, you can create its full key using its own identifier and a parent key, created with owner ID.
I have two models which naturally exist in a parent-child relationship. IDs for the child are unique within the context of a single parent, but not necessarily globally, and whenever I want to query a specific child, I'll have the IDs for both parent and child available.
I can implement this two ways.
Make the datastore key name of each child entity be the string "<parent_id>,<child_id>", and do joins and splits to process the IDs.
Use parent keys.
Option 2 sounds like the obvious winner from a code perspective, but will it hurt performance on writes? If I never use transactions, is there still overhead for concurrent writes to different children of the same parent? Is the datastore smart enough to know that if I do two transactions in the same entity group which can't affect each other, they should both still apply? Or should parent keys be avoided if locking isn't necessary?
In terms of the datastore itself, parent/child relationships are conceptual only. That is, the actual entities are not joined in any way.
A key consists of a Parent Key, a Kind and Id. This is the only link between them.
Therefore, there isn't any real impact beyond the ability to do things transactionally. Similarly, siblings have no actual relationship, just a conceptual one.
For example, you can put an entity into the datastore referencing a parent which doesn't actually exist. That is entirely legitimate and oftentimes very useful.
So, the only difference between option 1 and option 2 is that with option 1 you have to do more heavy lifting and cannot take advantage of transactions or strongly consistent queries.
Edit: The points above to do not mention the limitation of 1 write per entity group per second. So to directly answer the original question, using parent keys limits throughput if you want to write to many entities sharing the same parent key within a second outside of a single transaction.
In general, if you don't need two entities to be updated or read in the same transaction, they should not be in the same entity group, i.e. have similar roots in their key paths, as they would if one were a key-parent of the other. If they're in the same entity group, then concurrent updates to either entity will contend for the entire group, and some updates may need to be retried.
From your question, it sounds like "<parent_id>,<child_id>" is an appropriate key name for the child. If you need to access these IDs separately (such as to get all entities with a particular "<child_id>"), you can store them as indexed properties, and perform queries as needed.
For the transactions, you cannot do multiple concurrent writes
https://developers.google.com/appengine/docs/java/datastore/transactions#Java_What_can_be_done_in_a_transaction
How many Levels of master-Detail relationships can be created on salesforce object?
Just like multi-level inheritance in OOPs.
This page says you can have up to 3 custom detail levels:
https://help.salesforce.com/HTViewHelpDoc?id=relationships_considerations.htm
I'd be careful of having more than one level of detail objects. Remember that the child (and grandchild records) are also deleted when the parent (master) record is deleted. By default, it's not possible to re-parent child records. This is a feature that must be enabled for your Salesforce instance
Also, you can't directly do a summary roll-up for grandchild records. The child record will first need a roll-up for the grandchild.
How can I get the latest entry of a model new putted into NDB?
1: If I use a same parent key ? How to ?
I see the document write
Entities whose keys have the same root form an entity group or group.
If entities are in different groups, then changes to those entities
might sometimes seem to occur "out of order". If the entities are
unrelated in your application's semantics, that's fine. But if some
entities' changes should be consistent, your application should make
them part of the same group when creating them.
Is this means , with the same parent key the order is insert order?
But , how to get the last one ?
2: If I not use a same parent key (the model is same)? How to ?
If you're OK with eventual consistency (i.e. you might not see the very latest one immediately) you can just add a DateTimeProperty with auto_now_add=True and then run a query sorting by that property to get the latest one. (This is also approximate since you might have several entities saved close together which are ordered differently than you expect.)
If you need it to be exactly correct, the only way I can see is to create an entity whose job it is to hold a reference to the latest entry, and update that entity in the same transaction as the entry you're creating. Something like:
class LatestHolder(ndb.Model):
latest = ndb.KeyProperty('Entry')
# code to update:
#ndb.transactional(xg=True)
def put_new_entry(entry):
holder = LatestHolder.get_or_insert(name='fixed-key')
holder.latest = entry
holder.put()
entry.put()
Note that I've used a globally fixed key name here with no parent for the holder class. This is a bottleneck; you might prefer to make several LatestHolder entities with different parents if your "latest entry" only needs to be from a particular parent, in which case you just pass a parent key to get_or_insert.
Assumptions:
1) Google AppEngine has the concept of Entity Groups.
2) Entities in an entity group form a tree. However, as far as I understood, every put() to any entity in that tree will lock the whole tree (not just the immediate parent) for a while.
3) Users are allowed to write ca. 5 times per seconds to the tree.
4) There is no way to have a non-locking behaviour (i.e. by making them unindexed properties)
Would it be a smart idea to come up with my own parent-child model that does not use the built-in Key-functions (as those would create entity groups) but instead use some snytax convetions that I made up? This would allow me to retrieve a "child" entity via a query an compute the parent key.
The ancestor relationship used by entity groups can be modeled in your own code by using a list of references/keys to parent entities. Root entities will have none, children of roots will have just the root entity in their list, their children will have the root and their immediate parent, and so forth. This is how ancestors are implemented in App Engine for indexing purposes, and it'll permit you to make the same sorts of queries.
You can use a reference property:
class Parent(db.Model):
x = db.IntegerProperty()
class Child(db.Model):
parent = db.ReferenceProperty(
reference_class = Parent,
collection_name = 'children')
y = db.IntegerProperty()