0
votes

As the cloud firestore in datastore mode supports strong consistency for all queries,

https://cloud.google.com/datastore/docs/firestore-or-datastore#in_datastore_mode

could this be used to check for uniqueness? Say I have a user entity (top level entity) that has a datastore allocated ID as the key. In the past, it wasn't possible to do a query by email within the transaction as it was a global query. But it seems that it is now possible to do such queries as clarified at

New Google Cloud Firestore in Datastore mode Queries Clarification

Does this mean it is now possible to ensure there are no duplicate User entities by just indexing and querying by the email property within the transaction to insert the User entity?

My current implementation is to have a separate entity that has a named key using the email and do a key based query on that entity within the transaction. I can get rid of that if I can query by email on the User entity itself within the transaction and it guarantees duplicate entities won't be created under race condition.

2
According to cloud.google.com/datastore/docs/concepts/… , cloud datastore supports serializable isolation. At this highest level of isolation, it might work but the example given on that page is based on querying a named key not a property. Confirmation from someone closely familiar with datastore is what I am looking for.Siva
I noticed that when I use query.Transaction(tx), I still get the error "rpc error: code = InvalidArgument desc = Only ancestor queries are allowed inside transactions." Without that, I could do a global query within the transaction. So what does it mean that the queries are all strongly consistent in the datastore mode when it's still not allowed to do queries set to use transactions?Siva

2 Answers

1
votes

After some research, below is all I could gather.

  1. Even though datastore mode is strongly consistent, it is still not possible to use Global queries within transactions.
  2. As per https://cloud.google.com/datastore/docs/concepts/entities#creating_an_entity , it is possible to use a transaction, do get and based on the result do put but this is only possible with the uniqueness on the key.
  3. There are some strategies outlined at Google cloud datastore only store unique entity for this same issue and Dan suggested "insert" as opposed to "put". At first I didn't get this as Appengine Datastore api never had "Insert". But the Cloud Datastore Client API has Mutations which allow explicit insert (as opposed to put which maps to Upsert).
  4. As a result of the mutation support, I could use the same strategy of using a separate entity (different Kind) with key that maps to the unique property (such as email) but avoid an extra Get in the transaction. I do tx.Mutate on both the user entity and the uniqueness tracking entity with Named key on the email and try to insert both. This results in AlreadyExists error which can be used to track the violation.
0
votes

As of right now, there is no way to enforce uniqueness on a property. However, there are workarounds for what you are trying to do. One workaround is explained in the article linked above, and another is here.