Похоже, что объекты в хранилище данных используют свой ключ-предок как часть своего местоположения, можно ли на это полагаться?

#google-cloud-firestore #google-cloud-datastore

#google-cloud-firestore #google-cloud-datastore

Вопрос:

Вот моя тестовая настройка, запущенная в эмуляторе хранилища данных с gcloud beta emulators datastore start --no-store-on-disk

При использовании клиента NodeJS настройка выполняется следующим образом. Обратите внимание, что для целей примера я использую простые комбинации Вид Имя для предка. Я знаю, что документ «Лучшая практика» не поощряет монотонно генерируемые пользовательские имена.

 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
  

Я бы ожидал, что при запросе для всех Z объектов типа будет только 1 результат, если путь к предку не имел отношения к местоположению поиска объектов. Однако в моем тесте это не так, я получаю 4 результата обратно. Обратите внимание, что путь указан правильно для каждого объекта, возвращенного из запроса:

 [
    {
        "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"
    }
]
  

Итак, я хотел подтвердить, что это действительно правильное поведение, а не просто артефакт эмулятора. Если предполагается, что все работает именно так, из этого следует, что, возможно, можно подумать о создании временных рядов с использованием временных меток unix, если Вид Имя предка обеспечивает достаточную защиту от столкновения. В этом случае UUID, вероятно, будет достаточно, если процесс, запрашивающий запись, не выполняет запись в масштабе, который вызвал бы столкновение временных меток. В этом примере давайте предположим, что это 1 процесс на UUID, никогда больше.

 ['A', '95a69d2f-adac-4da7-b1ab-134ca0e7a840', 'Z', '1000000005000']
['A', '95a69d2f-adac-4da7-b1ab-134ca0e7a840', 'Z', '1000000006000']
['A', '95a69d2f-adac-4da7-b1ab-134ca0e7a840', 'Z', '1000000007000']
  

Или это все еще просто плохая идея?

Ответ №1:

Это правильное поведение, для объекта используется весь путь ключа, т. Е. он включает в себя все ключи-предки.

Если у вас есть уникальный (для каждого процесса) префикс, вам не нужно беспокоиться о монотонно увеличивающихся ключах, поскольку записи фактически распределяются в пространстве ключей вашим префиксом. Таким образом, это должно быть масштабируемое решение.