Why is project id attached to my Datastore Key object? - google-cloud-datastore

For some inexplicable reason, my project id is attached to the Key of my User entity:
<Key('User', 5703358593630208), project=my-project-id>
This is giving me issues, such as when I am trying to use this same key as an ancestor of another entity — I would get this error:
google.cloud.ndb.exceptions.BadValueError: Expected Key instance, got <Key('User', 5703358593630208), project=my-project-id>
I created the User entity like this:
from google.cloud import datastore
datastore_client = datastore.Client()
def save_user(name):
key = datastore_client.key('User')
user = datastore.Entity(key=key)
user.update({
'name': name,
'created': datetime.datetime.utcnow()
})
datastore_client.put(user)
Additional Example: Making an ancestral query
query = MyEntity.query(ancestor=user_key)
TypeError: ancestor must be a Key; received <Key('User', 5752652897976320), project=my-project-id>
What could be the explanation for this?

I believe the issue is that you are using both google.cloud.datastore and the NDB library and the key objects are not compatible. Here's an example of converting a datastore client key to an NDB key:
from google.cloud import datastore
from google.cloud import ndb
# Start with a google.cloud.datastore key
datastore_client = datastore.Client()
datastore_key = datastore_client.key('Parent', 'foo', 'User', 1234)
def key_to_ndb_key(key):
# Use flat_path property to create an ndb_key
key_path = key.flat_path
ndb_key = ndb.Key(*key_path)
return ndb_key
# Convert to a ndb key
ndb_client = ndb.Client()
with ndb_client.context() as context:
ndb_key = key_to_ndb_key(datastore_key)
print(ndb_key)

Entities are partitioned into subsets, currently identified by a project ID and namespace ID.
for more reference please check google doc and this.

Related

Is there a way to prefetch the autogenerated key .push() will generate in Firebase Realtime DB?

I would like to create a unique id for some of the objects I store in real time DB, but I would like the id to be in the object itself. Is there a way two do this without without a 3 stop process, e.g. push the object, read the key, update the db's id field with the key?
In other words, if I want my DB to look like this:
properties:
-Mfq1Ek2geCnkol7EbeW:
id: "-Mfq1Ek2geCnkol7EbeW"
buyer: "ab3s3aga"
seller: "b3skela"
-Mq1Em5a3skfjal3EjkVDMN:
id: "-Mq1Em5a3skfjal3EjkVDMN"
buyer: "zk39xlal"
seller: "34kzla99dl"
Is there a way to do that without having to write twice to the db?
When you call push() without arguments it's a pure client-side operation, that generates a new DatabaseReference object. You can get the key from this new object.
So (in JavaScript) you can get a new key with:
let newKey = ref.push().key;
Or you can keep the reference and the key like this:
let newRef = ref.push();
let newKey = newRef.key;
And then set a value to the new ref with:
newRef.set(...);

Corda - CommonQueryCriteria purpose of externalIds property

The Corda vault API contains a class called CommonQueryCriteria which is implemented like so:
abstract class CommonQueryCriteria : QueryCriteria() {
abstract val status: Vault.StateStatus
open val relevancyStatus: Vault.RelevancyStatus = Vault.RelevancyStatus.ALL
open val constraintTypes: Set<Vault.ConstraintInfo.Type> = emptySet()
open val constraints: Set<Vault.ConstraintInfo> = emptySet()
open val participants: List<AbstractParty>? = null
abstract val contractStateTypes: Set<Class<out ContractState>>?
open val externalIds: List<UUID> = emptyList()
open val exactParticipants: List<AbstractParty>? = null
override fun visit(parser: IQueryCriteriaParser): Collection<Predicate> {
return parser.parseCriteria(this)
}
}
What is the purpose of the externalIds property?
Note: This surely can't be meant to map UniqueIdentifier.externalId because:
There is a type mismatch (UUID vs. String?).
LinearStateQueryCriteria exists to query states by linearId or externalId.
This was introduced to support querying of accounts back in Corda 4.3:
https://github.com/corda/accounts/blob/master/docs.md#querying-the-vault-by-account
The Vault Query documentation mentions this new attribute right at the bottom of the page when discussing owning keys:
https://docs.corda.net/docs/corda-os/4.8/api-vault-query.html#mapping-owning-keys-to-external-ids
Admittedly it is not very clear and should reference CommonQueryCriteria (not VaultQueryCriteria) and show an example.
Though, if we look at the CreateAccount flow provided by the account library, the AccountInfo is created with a UniqueIdentifier with only an id :
val newAccountInfo = AccountInfo(
name = name,
host = ourIdentity,
identifier = UniqueIdentifier(id = identifier)
)
while the constructor of the UniqueIdentifier has both externalId and id:
data class UniqueIdentifier
constructor(val externalId: String? = null, val id: UUID = UUID.randomUUID())
So, effectively, if it is true that externalId was introduced to support queries with account, the vault queries are actually using the UniqueIdentifier.id of AccountInfo and not its externalId (assuming that nobody is creating an AccountInfo manually overriding the CreateAccount() function, as I suspect).

Looking at datastore field that is not indexed

I have an id field that is indexed and a boolean field x that is not indexed. Is there any way to view all the entities with x set to true without the following?
having a set of ids to filter by
scrolling through the UI page by page
Unfortunately, no. Cloud Datastore requires an index to query for a property. You could write a script to generate the list of IDs. For example, in python:
from google.cloud import datastore
client = datastore.Client()
query = client.query(kind='foo')
results = list(query.fetch())
for i in results:
if i['x'] == True:
print('Entity {} with id {} has x = True'.format(i.key, i['id']))

google datastore custom key using nodejs

I am using #google-cloud/datastore to save data in my entity.I have created the entity with custom key name = id.
How can I have a custom UUID as the key of the entity?
ds.save({
id: <uuid>,
data: Log
}).then(function () {
console.log(entities.map(fromDatastore));
});
const dsKey = ds.key({
namespace : namespace,// optional
path : ([kindName, id])
})
The key can be generated like this. The namespace is optional, if not provided the default namespace will be used. In the path kindname should be provided(if there is a parent kind for the provided kind, the path array value should begin from the root parent name and id) and the id can be any id you assign. If the id is not provided, datastore will generate a random id and assign it to the entity you inserted.
If you meant that you wanted the UUId as the complete key, that is not possible.

filter by id in ndb model

I am using ndb model as my databse. what i am trying to do is that filter the result on the basis of list of ids.
i have my model like :
class Photo(ndb.Model):
userid = ndb.StringProperty()
source = ndb.StringProperty()
handle = ndb.StringProperty()
sourceid =ndb.StringProperty()
So i am trying query like this:
queryset=Photo.query(Photo.key.id().IN(photoid_list))
I have also tried :
queryset=Photo.query(Photo.id().IN(photoid_list))
where photoid_list is the list of ids.
Help me out to solve it.
I would suggest that you create keys from each id and then get them all at once:
photo_keys = [ndb.Key(Photo, id) for id in photoid_list]
photos = ndb.get_multi(photo_keys)
The advantage is that a get is faster than a query. Also, ndb will memcache the entities by key and make subsequent gets even faster.
There are examples in the docs:
https://cloud.google.com/appengine/docs/python/ndb/queries#neq_and_in
So it looks like your query should be:
queryset=Photo.query(Photo.id.IN(photoid_list))

Resources