Как сканировать DynamoDB на наличие текста внутри списка?

В 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)

3

Решение

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

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

  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)
2

Другие решения

DynamoDB QueryFilter а также ScanFilter варианты в настоящее время не поддерживают CONTAINS оператор для карт. Вам нужно будет создать другую таблицу поиска, проиндексированную userName чтобы избежать сканирования всей таблицы.

Например. новая схема таблицы:

{
"userName": "[email protected]""orderId": "13aae31"}

Где ключ хеша userName а также orderId идентификатор заказа в другой таблице.

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

0

Если вы добавляете функцию «Поиск» в свое приложение, сканирование может быть не лучшим подходом.

Сканирование DynamoDB может быть дорогим и медленным, особенно если у вас много строк.

Поэтому, если вы собираетесь добавить функцию «Поиск», вы можете рассмотреть возможность использования AWS CloudSearch. Это масштабируемая функция поиска. Вы можете быстро включить «Поиск» из таблицы DynamoDB.

0
По вопросам рекламы [email protected]