Почему сканирование DynamoDB с помощью Limit и FilterExpression не возвращает элементы, соответствующие требованиям фильтра?

Мне нужно сделать сканирование с лимитом и условием на DynamoDB.

документы говорит:

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


Код (NODEJS):

var params = {
    ExpressionAttributeNames: {"#user": "User"},
    ExpressionAttributeValues: {":user": parseInt(user.id)},
    FilterExpression: "#user = :user and attribute_not_exists(Removed)",
    Limit: 2,
    TableName: "XXXX"
};

DynamoDB.scan(params, function(err, data) {
    if (err) {
        dataToSend.message = "Unable to query. Error: " + err.message;
    } else if (data.Items.length == 0) {
        dataToSend.message = "No results were found.";
    } else {
        dataToSend.data = data.Items;
        console.log(dataToSend);
    }
});



Таблица XXXX определений:

Основной ключ раздела: пользователь (номер)Основной ключ сортировки: идентификатор (строка)ИНДЕКС:Имя индекса: RemovedIndexТип: GSIКлюч раздела: удален (номер)Ключ сортировки: -Атрибуты: ВСЕ


В приведенном выше коде, если я удаляюLimit Параметр DynamoDB вернет элементы, которые соответствуют требованиям фильтра. Итак, условия в порядке. Но когда я сканирую сLimit параметр, результат пуст.

Таблица XXXX, имеет 5 предметов. Только 2 первых имеютRemoved приписывать. Когда я сканирую безLimit параметр, DynamoDB возвращает 3 элемента безRemoved приписывать.

Что я делаю не так?

Ответы на вопрос(4)

я думаю, вам просто нужно будет отсканировать всю таблицу до 1 МБ

Сканирование Набор результатов сканирования ограничен 1 МБ на вызов. Вы можете использоватьLastEvaluatedKey из ответа сканирования, чтобы получить больше результатов.

http://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Limits.html

пока не получите результаты

lastEvaluatedKey = null;
do {

    if(lastEvaluatedKey != null) {
        // query or scan data with last evaluated key 
    } else {
        // query or scan data WITHOUT last evaluated key 
    }        

    lastEvaluatedKey == key of last item retrieved

} while(lastEvaluatedKey != null && retrievedResultSize == 0); // == 0 or < yourLimit

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

Решение Вопроса

Если вы также предоставите значение FilterExpression, DynamoDB вернет элементыв первых шести которые также соответствуют требованиям фильтра

Комбинируя Limit и FilterExpression, вы приказали DynamoDB смотреть только первые два элемента в таблице и сравнивать FilterExpression с этими элементами. Предел в DynamoDB может сбивать с толку, потому что он работает иначеlimit в выражении SQL в СУБД.

 thismarcoantonio23 апр. 2018 г., 17:43
@SimonPertersen Спасибо!
 bozzmob16 янв. 2018 г., 20:05
@SimonPertersen Вы узнали ответ? Документация Динамо ужасна. Простые вещи, кажется, спрятаны где-то в дыре.
 thismarcoantonio20 апр. 2018 г., 16:22
@SimonPertersen, но как мне отфильтровать все поля таблицы, ограничить до 2 и разбить на страницы? Если я ограничу 2, он фильтрует только два первых поля таблицы.
 Simon Dragsbæk30 нояб. 2016 г., 09:41
@ Марк Б. Но как достичь этого «предела», как в выражении SQL в СУБД?
 thismarcoantonio19 апр. 2018 г., 21:27
@SimonPertersen, но если я не могу использовать что-то вроде эластичного, только динамо? Я думал запросить все данные, а затем вернуть данные, разрезанные по длине, но это плохое решение, потому что мне также нужно разбить на страницы ...
 Simon Dragsbæk23 апр. 2018 г., 16:06
Локальные индексы @thismarcoantonio предназначены для того, если вам нужен вторичный ключ диапазона для исходного хэш-ключа, для глобального - если вам нужны новые глобальные хэш-ключи.
 thismarcoantonio23 апр. 2018 г., 15:57
@SimonPertersen Я вижу ... когда вы говорите об индексах, говорите о вторичных индексах? Если да, глобальные индексы или локальные индексы? Потому что мне нужно платить за каждый глобальный индекс, конечно?
 Mark B14 авг. 2016 г., 16:24
@Clarkie Это полезно, поскольку позволяет ограничить количество записей, которые оценивает операция сканирования, из соображений производительности. Тот факт, что он не работает так же, как СУБД, не означает, что он бесполезен. Также ваш комментарий на Github о том, что «некоторая путаница из-за того, что говорят документы», кажется мне неверным. Документы (как я цитировал в моем ответе) совершенно ясны. Путаница исходит от людей, которые предполагаютlimit В DynamoDB работает так же, как и в RDBMS, не тратя время на чтение документов.
 Simon Dragsbæk22 янв. 2018 г., 16:37
@bozzmob хорошо зависит от того, что вы делаете, мой подход состоит в том, чтобы использовать DynamodB для простого CRUD, затем я использую лямбду AWS для индексации определенных таблиц для упругого поиска, а затем выполняю тяжелые запросы в упругом
 Simon Dragsbæk23 апр. 2018 г., 08:31
@thismarcoantonio Это из-за дерьмовой идеи, которая у них есть в динамо, которая применяет фильтры после их возвращения - лучший способ решить это с помощью индексов - или использовать потоки, чтобы иметь их в упругом поиске и выполнять сложные запросы
 Gabriel Cunha05 авг. 2016 г., 01:11
Спасибо за ваш ответ! Я не понял документ, вы мне разъяснили. Есть ли у вас какие-либо советы о том, как я могу использоватьlimit как выражение SQL в СУБД?
 Simon Dragsbæk17 янв. 2018 г., 09:35
@bozzmob Я еще не нашел решения, все еще сомневаюсь. Это связано с основными идеями дизайна в Dynamodb, где фильтры добавляются после лимита.
 bozzmob17 янв. 2018 г., 10:49
@SimonPertersen, глядя на несколько вещей, я чувствую, что DynamoDB - не правильный выбор для моего варианта использования. MongoDB имеет гораздо лучшие шаблоны запросов. Я мог бы пойти с MongoDB или Cassandra.
 Simon Dragsbæk20 апр. 2018 г., 08:59
@thismarcoantonio вы можете разбить на страницы, просто разобрать 'startKey'
 Clarkie14 авг. 2016 г., 16:09
Там определенно некоторая путаница по этому поводу:github.com/clarkie/dynogels/issues/12 Как это полезное поведение? Наверняка сканирование, пока у вас не будет 6 элементов, соответствующих фильтру, или вы дойдете до конца таблицы, было бы более полезным?

что вам нужно, используя вторичный индекс. Используя классический пример RDB, пример заказа клиента: у вас есть одна таблица для клиентов и одна для заказов. Таблица заказов имеет ключ, состоящий из клиента - HASH, заказ - RANGE. Так что, если вы хотите получить последние 10 заказов, не было бы способа сделать это без сканирования

Но если вы создадите глобальный вторичный индекс по порядку «Некоторая константа» - HASH, Date RANGE и запросите его по этому индексу, они будут делать то, что вы хотите, и взимать плату только за RCU, связанные с возвращенными записями. Не требуется дорогостоящее сканирование. Обратите внимание, что запись будет дороже, но в большинстве случаев чтения намного больше, чем записи.

Теперь у вас есть исходная проблема, если вы хотите получить 10 самых больших заказов на день, превышающий 1000 долларов. Запрос вернет последние 10 заказов, а затем отфильтрует те, которые меньше 1000 долларов.

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

Это не так просто, как SQL, но вам нужно подумать и о шаблонах доступа в SQL. Если у вас много данных, вам нужно создать индексы в SQL, или БД с радостью выполнит сканирование таблиц от вашего имени, что снизит производительность и увеличит ваши затраты.

Обратите внимание, что все, что я предложил, нормализовано в том смысле, что существует только один источник правды. Вы не дублируете данные - вы просто переделываете их, чтобы получить то, что вам нужно от DynamoDB.

Имейте в виду, что CONSTANT, как HASH, ограничен пределом в 10 ГБ на раздел, поэтому вам придется создавать его, если у вас много активных данных. Например, в зависимости от ожидаемого шаблона доступа, вы можете использовать Customer, а не константу в качестве HASH. Или используйте STreams для организации данных (или подмножеств) другими способами.

Ваш ответ на вопрос