Parece que las entidades en el almacén de datos usan su clave ancestral como parte de su ubicación, ¿se puede confiar en esto?
Aquí está mi configuración de prueba ejecutándose en el emulador de Datastore con gcloud beta emulators datastore start --no-store-on-disk
Usando el cliente NodeJS, la configuración es la siguiente. Tenga en cuenta que para el propósito del ejemplo, estoy usando combinaciones simples de Tipo + Nombre para el antepasado. Soy consciente de que el documento de mejores prácticas desalienta los nombres personalizados generados de manera monótona.
const namespace = 'test';
const datastore = new Datastore();
const entities: any[] = [];
const paths = [
['A', '1', 'Z', '1'],
['A', '2', 'Z', '1'],
['A', '3', 'Z', '1'],
['A', '4', 'Z', '1'],
];
for (const path of paths) {
const key = datastore.key({ path, namespace });
const data = {
text: 'Lorem Ipsum',
path: key.path.toString(),
};
entities.push({ key, data });
}
const transaction = datastore.transaction();
await transaction.run();
transaction.upsert(entities);
await transaction.commit();
// wait a second for things to persist.
await new Promise((resolve) => {
setTimeout(() => resolve(), 1000);
});
// Note that `hasAncestor` is **NOT** provided for this query.
const query = datastore.createQuery(namespace, 'Z');
const results = await datastore.runQuery(query);
expect(results[0]).toHaveLength(1); // fails, got 4 records back
Esperaría que solo hubiera 1 resultado al consultar todas las Z
entidades de tipo si la ruta del ancestro no tuviera relación con la ubicación de búsqueda de las entidades. Ese no es el caso en mi prueba, sin embargo, obtengo 4 resultados. Tenga en cuenta que la ruta es correcta entre cada entidad devuelta por la consulta:
[
{
"path": "A,1,Z,1",
"text": "Lorem Ipsum"
},
{
"path": "A,2,Z,1",
"text": "Lorem Ipsum"
},
{
"path": "A,3,Z,1",
"text": "Lorem Ipsum"
},
{
"path": "A,4,Z,1",
"text": "Lorem Ipsum"
}
]
Así que quería confirmar que este es de hecho el comportamiento correcto y no solo un artefacto del emulador. Si así es como se supone que funcionan las cosas, se deduciría que quizás esté bien considerar hacer una serie de tiempo usando marcas de tiempo Unix siempre que el Tipo + Nombre del antepasado proporcione suficiente protección contra colisiones. En este caso, es probable que un UUID sea suficiente siempre que el proceso que solicita la escritura no escriba a una escala que provoque una colisión de marca de tiempo. En este ejemplo, supongamos que es 1 proceso por UUID nunca más.
['A', '95a69d2f-adac-4da7-b1ab-134ca0e7a840', 'Z', '1000000005000']
['A', '95a69d2f-adac-4da7-b1ab-134ca0e7a840', 'Z', '1000000006000']
['A', '95a69d2f-adac-4da7-b1ab-134ca0e7a840', 'Z', '1000000007000']
¿O sigue siendo una mala idea?
Respuestas
Este es el comportamiento correcto en el que una entidad está codificada por la ruta completa de la clave, es decir, incluye todas las claves ancestrales.
Si tiene un prefijo único (por proceso), no tendrá que preocuparse por las claves que aumentan monótonamente, ya que las escrituras están espaciadas en el espacio de claves por su prefijo. Por tanto, esta debería ser una solución escalable.