2015-04-25 2 views
2

Предположим, моя таблица выглядит следующим образом:DynamoDB «ИЛИ» условный диапазон запросов

Code |StartDate |EndDate |Additional Attributes... 

ABC  |11-24-2015 |11-26-2015 | .... 

ABC  |12-12-2015 |12-15-2015 | .... 

ABC  |10-05-2015 |10-10-2015 | .... 

PQR  |03-24-2015 |03-27-2015 | .... 

PQR  |05-04-2015 |05-08-2015 | .... 

предоставлен код (с) и диапазон дат (х, у), мне нужно, чтобы иметь возможность запрашивать элементы что-то вроде :

Query => (Code = c) AND ((StartDate BETWEEN x AND y) OR (EndDate BETWEEN x AND y)) 

Я планировал использовать первичный ключ в качестве хэша и Range Key (код, StartDate) с дополнительным БИС (EndDate) и сделать запрос на него. Я не уверен, есть ли способ достичь этого. Я не хочу использовать операцию SCAN, поскольку она, кажется, сканирует всю таблицу, которая может быть очень дорогостоящей.

Также хотелось бы достичь этого в одном запросе.

+0

Сохраняются ли ваши даты в этом формате? '05-04-2015'? Есть гораздо лучшие способы [хранить однозначные даты] (http://stackoverflow.com/questions/9576860/sort-iso-iso-8601-dates-forward-or-backwards), так как '05-04-2015' может интерпретироваться как «04 мая 2015 года» или «5 апреля 2015 года». – mkobit

+0

спасибо, спасибо –

ответ

1

Один вариант должен был бы сделать это с использованием QUERY и FilterExpression. Нет необходимости определять LSI на этом футляре. Вам нужно будет запросить Hash Key с оператором EQ, а затем сузить результаты с помощью выражения фильтра. Вот пример с Java SDK:

Table table = dynamoDB.getTable(tableName); 

Map<String, Object> expressionAttributeValues = new HashMap<String, Object>(); 
expressionAttributeValues.put(":x", "11-24-2015"); 
expressionAttributeValues.put(":y", "11-26-2015"); 

QuerySpec spec = new QuerySpec() 
    .withHashKey("Code", "CodeValueHere") 
    .withFilterExpression("(StartDate between :x and :y) or (EndDate between :x and :y)") 
    .withValueMap(expressionAttributeValues); 


ItemCollection<QueryOutcome> items = table.query(spec); 

Iterator<Item> iterator = items.iterator(); 

while (iterator.hasNext()) { 
    System.out.println(iterator.next().toJSONPretty()); 
} 

См Specifying Conditions with Condition Expressions для более подробной информации.

Кроме того, хотя в предыдущем запросе используется только Hash Key, вы все еще можете сгруппировать записи с Range Key, содержащий даты в следующем формате:

StartDate # EndDate

Структура таблицы:

Code DateRange    |StartDate |EndDate   
ABC  11-24-2015#11-26-2015 |11-24-2015 |11-26-2015 

ABC  12-12-2015#12-15-2015 |12-12-2015 |12-15-2015 

ABC  10-05-2015#10-10-2015 |10-05-2015 |10-10-2015 

PQR  03-24-2015#03-27-2015 |03-24-2015 |03-27-2015 

PQR  05-04-2015#05-08-2015 |05-04-2015 |05-08-2015 

Этот способ Если вам послан запрос только Hash Key, вы все равно получите записи, отсортированные по датам. Кроме того, я считаю, что неплохо следовать рекомендациям, касающимся однозначной даты format.nu

+0

Я чувствую, что это будет серьезной проблемой, если мощность hashkey низкая. Поскольку он извлекает все записи с помощью этого хэш-ключа, а затем запускает фильтр для удаления записей. Знаете ли вы, каково влияние на CapacityUnits, потребляемых для таких чтений. Будет ли какое-либо улучшение в процедуре запроса, чтобы добавить два глобальных индекса. (начальная и конечная). Или он будет проходить через все записи, извлеченные на хэш-ключ. –

+0

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

Смежные вопросы