Подтвердить что ты не робот

Запрос DynamoDB по дате

Я исхожу из реляционной базы данных и пытаюсь работать с amazon DynamoDB

У меня есть таблица с хеш-ключом "DataID" и диапазон "CreatedAt" и куча элементов в нем.

Я пытаюсь получить все элементы, созданные после определенной даты и отсортированные по дате. Это довольно просто в реляционной базе данных.

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

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

4b9b3361

Ответ 1

Обновленный ответ:

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

Для варианта использования в этом вопросе вы бы хотели использовать глобальный вторичный индекс в поле "CreatedAt".

Подробнее о вторичных индексах DynamoDB см. документацию вторичного индекса

Оригинальный ответ:

DynamoDB не позволяет индексировать запросы только на ключ диапазона. Хеш-ключ необходим, чтобы служба узнала, какой раздел искать, чтобы найти данные.

Вы можете, конечно, выполнить операцию сканирования для фильтрации по значению даты, однако для этого потребуется полное сканирование таблицы, поэтому оно не является идеальным.

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

Ответ 2

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

Запросы могут выполняться только в одном разделе. Это действительно конец истории. Это означает, что если вы хотите выполнить запрос по дате (вы хотите использовать msec с эпохи), тогда все элементы, которые вы хотите получить в одном запросе, должны иметь один и тот же Hash (раздел).

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

У вас может возникнуть соблазн поместить все данные в один раздел для решения проблемы, и вы абсолютно можете, однако ваша пропускная способность будет болезненно низкой, учитывая, что каждый раздел получает только часть от общей установленной суммы.

Лучшее, что нужно сделать, это определить более полезные разделы для создания для сохранения данных:

  • Вам действительно нужно посмотреть на все строки или это только строки определенного пользователя?

  • Можно ли сначала сузить список по месяцам и сделать несколько запросов (по одному на каждый месяц)? Или Годом?

  • Если вы проводите анализ временных рядов, есть несколько вариантов, измените ключ раздела на что-то, вычисленное на PUT, чтобы сделать query проще, или используйте другой продукт aws, такой как кинезис, который поддается только для регистрации в приложении.

Ответ 3

Ваша клавиша Hash (первичная сортировка) должна быть уникальной (если у вас нет диапазона, как указано другими). ​​

В вашем случае для запроса вашей таблицы вы должны иметь вторичный индекс.

|  ID  | DataID | Created | Data |
|------+--------+---------+------|
| hash | xxxxx  | 1234567 | blah |

Ваш хэш-ключ - это идентификатор Ваш вторичный индекс определяется как: DataID-Created-index (имя, которое будет использовать DynamoDB)

Затем вы можете сделать такой запрос:

var params = {
    TableName: "Table",
    IndexName: "DataID-Created-index",
    KeyConditionExpression: "DataID = :v_ID AND Created > :v_created",
    ExpressionAttributeValues: {":v_ID": {S: "some_id"},
                                ":v_created": {N: "timestamp"}
    },
    ProjectionExpression: "ID, DataID, Created, Data"
};

ddb.query(params, function(err, data) {
    if (err) 
        console.log(err);
    else {
        data.Items.sort(function(a, b) {
            return parseFloat(a.Created.N) - parseFloat(b.Created.N);
        });
        // More code here
    }
});

По существу ваш запрос выглядит так:

SELECT * FROM TABLE WHERE DataID = "some_id" AND Created > timestamp;

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

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

Ответ 4

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

Hash Key                 | Range Key
------------------------------------
Date value of CreatedAt  | CreatedAt

Ограничение, наложенное на пользователя API HTTP, указать количество дней для извлечения данных, по умолчанию - 24 часа.

Таким образом, я всегда могу указать HashKey как текущий день, и RangeKey может использовать > и < операторы при извлечения. Таким образом, данные также распространяются на несколько осколков.

Ответ 5

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

Ответ 6

У вас может быть несколько идентичных хэш-ключей; но только если у вас есть ключ диапазона, который меняется. Думайте об этом как о форматах файлов; вы можете иметь 2 файла с тем же именем в одной папке, если их формат отличается. Если их формат совпадает, их имя должно быть другим. Такая же концепция применяется к клавишам хэша/диапазона DynamoDB; просто подумайте о хеше как о названии и диапазоне как формате.

Кроме того, я не помню, имели ли они их во время OP (я не думаю, что они это сделали), но теперь они предлагают локальные вторичные индексы.

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

Я все же рекомендую ответить Майку Бранту как предпочтительный метод использования DynamoDB; и использовать этот метод самостоятельно. В моем случае у меня просто есть центральная таблица с только хэш-ключом в качестве моего идентификатора, а затем вторичные таблицы, которые имеют хэш и диапазон, которые могут быть запрошены, тогда элемент указывает код на центральную таблицу "интересующий объект", непосредственно.

Дополнительные данные относительно вторичных индексов можно найти в документации Amazon DynamoDB здесь для заинтересованных лиц.

В любом случае, надеюсь, это поможет кому-то еще, что происходит в этой теме.

Ответ 7

Вы можете сделать это сейчас в DynamoDB, используя GSI. Создайте поле "CreatedAt" как GSI и задайте такие запросы, как (GT some_date). Сохраните дату в виде числа (мсек с эпохи) для таких запросов.

Подробности доступны здесь: Глобальные вторичные индексы - Amazon DynamoDB: http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html#GSI.Using

Это очень мощная функция. Имейте в виду, что запрос ограничен (EQ | LE | LT | GE | GT | BEGINS_WITH | BETWEEN) Состояние - Amazon DynamoDB: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Condition.html