В DynamoDB у меня есть таблица со следующей структурой.
actions
«Поле» содержит всю информацию (и это поле, в котором я хотел бы искать) и orderId
это первичный ключ
{
"actions": [
{
"actionDescription": "8f23029def1d6baa4",
"actionTitle": "UNDEFINED_ACTION",
"timestamp": 1533730680,
"user": {
"fullName": "XXXXX",
"userName": "[email protected]",
}
},
{
"actionDescription": "21857e61037bc29ec",
"actionTitle": "UNDEFINED_ACTION",
"timestamp": 1533731788,
"user": {
"fullName": "XXXXX",
"userName": "[email protected]",
}
},
{
"actionDescription": "cf10abd44e24cef56",
"actionTitle": "UNDEFINED_ACTION",
"timestamp": 1533731788,
"user": {
"fullName": "XXXXX",
"userName": "[email protected]",
}
},
{
"actionDescription": "7787fe7a5bf4d22de",
"actionTitle": "UNDEFINED_ACTION",
"timestamp": 1533731789,
"user": {
"fullName": "OOOOOO",
"userName": "[email protected]",
}
},
{
"actionDescription": "9528c439021f504bf",
"actionTitle": "UNDEFINED_ACTION",
"timestamp": 1533731789,
"user": {
"fullName": "XXXXX",
"userName": "[email protected]",
}
},
{
"actionDescription": "bfba100e0e54934b2",
"actionTitle": "UNDEFINED_ACTION",
"timestamp": 1533731789,
"user": {
"fullName": "XXXXX",
"userName": "[email protected]",
}
},
{
"actionDescription": "f789dc12f1dbe3be2",
"actionTitle": "UNDEFINED_ACTION",
"timestamp": 1533731789,
"user": {
"fullName": "OOOOOO",
"userName": "[email protected]",
}
},
{
"actionDescription": "4cd6b68dfea7cf8ee",
"actionTitle": "UNDEFINED_ACTION",
"timestamp": 1533731789,
"user": {
"fullName": "XXXXX",
"userName": "[email protected]",
}
},
{
"actionDescription": "1e3a0e95f8e5106d7",
"actionTitle": "UNDEFINED_ACTION",
"timestamp": 1533731790,
"user": {
"fullName": "OOOOOO",
"userName": "[email protected]",
}
}
],
"orderId": "13aae31"}
То, что я хотел бы сделать, это сделать условия сканирования в PHP, чтобы иметь возможность поиска по userName
, или любым полем внутри массива действий (timestamp, actionTitle и т. д., и т. д.).
Ниже это один из многих терминов, которые я пытался использовать, но я не смог достичь каких-либо результатов
$params = [
'TableName' => $this->tableName,
'FilterExpression' => "userName = :searchTerm",
'ExpressionAttributeValues' => [
':searchTerm' => '[email protected]',
],
'ReturnConsumedCapacity' => 'TOTAL',
];
$results = $this->dynamoDbClient->scan($params);
Можете ли вы направить меня, рассказав мне, что я скучаю?
Также обратите внимание: я не хочу получать конкретный orderId
Я хотел бы получить ВСЕ orderIds
содержащий searchTerm (в этом случае userName
)
Лучше всего использовать эту схему элементов для самостоятельной фильтрации элементов таблицы. То есть отсканируйте таблицу без выражения фильтра и напишите собственный код для фильтрации результатов. Сканирование без экспресс-фильтра будет занимать такое же количество единиц емкости чтения.
Вы можете установить выражение фильтра на что-то вроде этого, однако это не масштабируется и работает, только если у вас есть фиксированное количество элементов в списке действий.
actions[0].user.userName == :searchTerm OR actions[1].user.userName == :searchTerm OR actions[2].user.userName == :searchTerm OR ....
Если вам нужны сложные возможности поиска, вы, вероятно, лучше использовать выделенную базу данных поиска. AWS предоставляет две услуги: AWS CloudSearch и AWS ElasticSearch. Вы можете использовать потоки DynamoDB, чтобы обновлять поисковые индексы.
Если вы настроены на сканирование таблицы DynamoDB с помощью фильтра, вы можете реорганизовать свою структуру, включив в нее дополнительные атрибуты, которые содержат всю информацию для поиска в наборе (или объединенной строке)
{
"actions": [....],
"actionsDescriptions": Set["8f23029def1d6baa4", "21857e61037bc29ec", "cf10abd44e24cef56", "7787fe7a5bf4d22de", "9528c439021f504bf", "bfba100e0e54934b2", "f789dc12f1dbe3be2", "4cd6b68dfea7cf8ee", "1e3a0e95f8e5106d7"],
"actionTitles": Set["UNDEFINED_ACTION"],
"timestamps": Set[1533730680, 1533731788, 1533731789, 1533731790],
"user_fullNames": Set["XXXXX"],
"user_userNames": Set["[email protected]", "[email protected]"],
"orderId": "13aae31"}
Обратите внимание, что вы должны использовать Set (или объединить все значения в строку), так как contains
Функция работает только со строками и множествами.
Тогда вы можете использовать выражение фильтра, как это
contains(user_userNames, :searchTerm)
DynamoDB QueryFilter
а также ScanFilter
варианты в настоящее время не поддерживают CONTAINS
оператор для карт. Вам нужно будет создать другую таблицу поиска, проиндексированную userName
чтобы избежать сканирования всей таблицы.
Например. новая схема таблицы:
{
"userName": "[email protected]""orderId": "13aae31"}
Где ключ хеша userName
а также orderId
идентификатор заказа в другой таблице.
Самое близкое, что вы можете получить с текущей схемой, это использовать @cementblocksПредлагает отсканировать всю таблицу и отфильтровать на стороне приложения или запросить каждый элемент в списке по отдельности.
Если вы добавляете функцию «Поиск» в свое приложение, сканирование может быть не лучшим подходом.
Сканирование DynamoDB может быть дорогим и медленным, особенно если у вас много строк.
Поэтому, если вы собираетесь добавить функцию «Поиск», вы можете рассмотреть возможность использования AWS CloudSearch. Это масштабируемая функция поиска. Вы можете быстро включить «Поиск» из таблицы DynamoDB.