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

Aug 20 2020

Вот моя тестовая установка, работающая в эмуляторе Datastore с gcloud beta emulators datastore start --no-store-on-disk

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

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, если Kind + Name предка обеспечивает достаточную защиту от столкновений. В этом случае 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']

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

Ответы

JimMorrison Aug 20 2020 at 23:14

Это правильное поведение, когда сущность вводится по всему пути ключа, т. Е. Включает все ключи предков.

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