DynamoDB Как проектировать и запрашивать несколько полей - PullRequest
0 голосов
/ 06 октября 2019

У меня есть такой предмет

{
  "date": "2019-10-05",
  "id": "2",
  "serviceId": "1",
  "time": {
    "endTime": "1300",
    "startTime": "1330"
  }
}

Прямо сейчас мой дизайн выглядит примерно так:

primary key --> id
Global secondary index --> primary key : serviceId
                       --> sort key : date

С тем, как я задумал,

* I can query the id
* I can query serviceId and range of date

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

* serviceId = 1 AND
* date = "yyyy-mm-dd" AND
* time = {
           "endTime": "1300",
           "startTime": "1330"
         }

Я все еще хотел бы иметь возможность запрашивать на основе 2 предыдущих условий (запроспо id, и запрос по serviceId и rangeOfDate

Есть ли способ сделать это? Один из способов, который я подумал, - создать новое поле и использовать его в качестве индекса, например: объединить все данные, так комбинированныеField: "1_yyyy-mm-dd_1300_1330

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

Я просто не уверен, что это способ сделать это или есть лучшийили лучший способ сделать это?

Спасибо

Ответы [ 2 ]

2 голосов
/ 06 октября 2019

Вы можете использовать FilterExpression или составные ключи сортировки.

FilterExpression

Здесь вы можете получить элементы из GSI, который вы описали, указав «serviceId» и «date», а затем указавв выражении FilterExpression, указывающем time.startTime и time.endTime. Пример кода Python с использованием boto3 будет выглядеть следующим образом:

response = table.query(
    KeyConditionExpression=Key('serviceId').eq(1) & Key('date').eq("2019-10-05"),
    FilterExpression=Attr(time.endTime).eq('1300') & Attr('time.startTime').eq('1330')
)

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

Например: если 1000 элементов имеют «serviceId» в качестве 1 и «date» в качестве «2019-10-05», но только 10 элементов имеют «time.startTime 'как 1330, тогда вы все равно будете платить за чтение 1000 элементов, даже если после применения FilterExpression будет возвращено только 10 элементов.

Ключ составной сортировки

Я считаю, что этоэто метод, который вы упомянули в вопросе. Здесь вам нужно сделать атрибут как

'yyyy-mm-dd_startTime_endTime'

и использовать его в качестве ключа сортировки в GSI. Теперь ваши элементы будут выглядеть так:

{   "date": "2019-10-05",
    "id": "2",
    "serviceId": "1",
    "time": {
        "endTime": "1300",
        "startTime": "1330"
    }
    "date_time":"2019-10-05_1330_1300"
}

Ваш GSI будет иметь «serviceId» в качестве ключа раздела и «date_time» в качестве ключа сортировки. Теперь вы сможете запросить диапазон дат как:

response = table.query(
    KeyConditionExpression=Key('serviceId').eq(1) & Key('date').between('2019-07-05','2019-10-05')
)

Для запроса, в котором указаны дата, время начала и окончания, вы можете запросить как:

response = table.query(
    KeyConditionExpression=Key('serviceId').eq(1) & Key('date').eq('2019-10-05_1330_1300')
)

Этот подход выигралне работает, если вам нужен диапазон дат и время начала и окончания вместе, т.е. Вы не сможете сделать запрос для элементов в определенном диапазоне дат, содержащих определенное время начала и окончания. В этом случае вам придется использовать FilterExpression.

0 голосов
/ 06 октября 2019

Да, решение, которое вы предложили (добавьте новое поле, которое является комбинацией полей и определило GSI для него), является стандартным способом достижения этого. Вам необходимо убедиться, что символ, который вы используете для объединения, уникален, т. Е. Он не может появиться ни в одном из отдельных полей, которые вы комбинируете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...