Reputation: 277
I'm trying to better understand the implications of the deep hierarchy described in the GAE NDB docs
"For example, a revision of a message that "belongs to" an owner, might have a key that looks like"
rev_key = ndb.Key('Account', 'Sandy', 'Message', 'greeting', 'Revision', '2')
I interpret this to mean that if I do Revision(parent=rev_key).put()
then I will have an entity group at the Revision=2 level meaning ancestor queries where ancestor=rev_key
will have strong consistency and writes where parent=rev_key
will be limited to 1/sec.
But what are the implications further up the hierarchy?
For instance, say I have
rev_key_B = ndb.Key('Account', 'Sandy', 'Message', 'greeting', 'Revision', '3')
Is write speed limited to 1/sec at the rev_key_B
level or, since they share a parent's parent, i.e. ndb.Key('Account', 'Sandy', 'Message', 'greeting')
, is write speed limited even higher up the ancestor path and, ultimately, to the entire entity group all the way up to ndb.Key('Account', 'Sandy')
?
Same questions re: strong consistency. Would Revision.query(ancestor=ndb.Key('Account', 'Sandy', 'Message', 'greeting'))
have strong consistency?
Upvotes: 3
Views: 865
Reputation: 16825
Let's see
rev_key = ndb.Key('Account', 'Sandy', 'Message', 'greeting', 'Revision', '2')
Means that every entity has strong consistency following the entity path. So you are correct.
Lets see it in action: Create the entities
account_sandy = Account.get_or_insert('Sandy')
sandy_message = Message.get_or_insert('greeting', parent=account_sandy.key)
sandy_message_rev = Revision.get_or_insert('2', parent=sandy_message.key)
That will give you strong consistency and grant you the ability to query all the above entities inside transactions as well.
I am using the get_or_insert
which does what it says inside a transaction efficiently creating an entity if it does not exist with the key provided. This requires the key or id to be unique. So this way you cannot have 2 messages with Greeting
and Sandy as parent
.
The way keys work is like a binary tree.
S = Sandy, M=Message, R=Revision
Sandy
/ | \
M1 M2 M3
/ | \ | \
R1 R2 R1 R1 R2
Each path to the end or shorter can be run in transaction and provide strong consistency*.
Reply in comment:
As this example is not sufficient to show the efficiency of GAE and NDB maybe the below will.
Imagine that you have a jukebox with queues per room let's say. And people are queueing songs to each queue of each jukebox.
J=Jukebox, Q=queue, S=Song
Jukebox
/ | \
Q1 Q2 Q3
/ | \ | \
S1 S2 S3 S4 S5
In this example it is convenient to use paths, so each operation by a user, knowing wich jukebox, queue can CUD the song entity with consistency to jukebox, queue and song.
*Btw you can also lock paths not starting from root
Also keep in mind that Queries inside transactions must include ancestor filters
Upvotes: 1