Как отфильтровать объект вложенного массива в DynamoDB

Я очень новичок в AWS DynamoDB, я хочу сканировать DynamoDB с помощью SENDTO.emailAddress = "[email protected]" в качестве выражения фильтра.

Структура БД выглядит так

{
    ID
    NAME
    MESSAGE
    SENDTO[
        {
            name
            emailAddress
        }
    ]
}

Пример данных

{
    ID: 1,
    NAME: "HELLO",
    MESSAGE: "HELLO WORLD!",
    SENDTO: [
        {
            name: "First",
            emailAddress: "[email protected]"
        },
        {
            name: "Second",
            emailAddress: "[email protected]"
        }
    ]
}

Я хочу получить документ, соответствующий адресу электронной почты. Я попытался сканировать с помощью выражения фильтра, и вот мой код для извлечения данных. Я использую SDK AWS Javascript.

let params = {
    TableName : "email",
    FilterExpression: "SENDTO.emailAddress = :emailAddress",
    ExpressionAttributeValues: {
        ":emailAddress": "[email protected]",
    }
}

let result = await ctx.docClient.scan(params).promise();

person Narayanan Ramanathan    schedule 14.11.2017    source источник
comment
Вы можете получить данные из таблицы dynamodb, используя ключ раздела или комбинацию ключа раздела и ключа сортировки. С другой стороны, вы можете использовать индексы.   -  person Dmitry Grinko    schedule 15.11.2017
comment
Я пробовал использовать ключ раздела и ключ сортировки, это не помогло, я читал, что эта операция не поддерживается DynamoDB. Мы можем запросить атрибут объекта, но не атрибут массива объектов.   -  person Narayanan Ramanathan    schedule 15.11.2017
comment
я обновил свой ответ   -  person Dmitry Grinko    schedule 15.11.2017


Ответы (2)


Чтобы найти элемент по атрибуту sendto, вам нужно знать значение атрибута name и emailAddress. DynamoDB не может найти данные только по одному из атрибутов в объекте (то есть только по значению атрибута email).

Функцию CONTAINS можно использовать для поиска данных в виде списка.

CONTAINS поддерживается для списков: при вычислении «a CONTAINS b» «a» может быть списком; однако «b» не может быть набором, картой или списком.

Пример кода с использованием Contains:-

var params = {
    TableName: "email",
    FilterExpression: "contains (SENDTO, :sendToVal)",
    ExpressionAttributeValues: {
        ":sendToVal": {
            "name" : "First",
            "emailAddress" : "[email protected]"
        }
    }
}; 

Если вы не знаете значения атрибутов name и emailAddress, вам может потребоваться изменить данные для выполнения вашего варианта использования.

person notionquest    schedule 15.11.2017
comment
Да, спасибо, я переделал данные как два отдельных массива. - person Narayanan Ramanathan; 15.11.2017
comment
Если вы храните два отдельных массива, как бы вы связали имя и адрес электронной почты? - person notionquest; 15.11.2017
comment
Это сравнивает весь объект, что может быть полезно. Как нам просто проверить одно поле карты? - person foxtrotuniform6969; 29.09.2018

Я думаю, что вам следует создать две таблицы для пользователей и для сообщений.

В таблице пользователей есть partition_key: user_id и sort_key: электронная почта, а также поле с массивом идентификаторов его сообщений.

Таблица сообщений имеет partition_key: message_id и поле с массивом идентификаторов пользователей.

Когда вы получите массив идентификаторов пользователей, вы можете использовать запрос BATCH GET, чтобы получить всех пользователей одного сообщения.

Когда вы получите массив идентификаторов сообщений, вы можете использовать запрос BATCH GET, чтобы получить все сообщения одного пользователя.

Если вы хотите получить одного пользователя по электронной почте, вы можете использовать метод QUERY.

Документы

person Dmitry Grinko    schedule 15.11.2017
comment
Спасибо, я переделал данные как два отдельных массива. Но в DynamoDB нет возможности выполнить вышеуказанную операцию. - person Narayanan Ramanathan; 15.11.2017
comment
Вы должны использовать documentClent для этого - person Dmitry Grinko; 15.11.2017
comment
я дал тебе ссылку - person Dmitry Grinko; 15.11.2017
comment
Да, я использовал documentClient и попробовал ваше решение, оно сработало, но я хочу, чтобы данные были в виде одного документа. - person Narayanan Ramanathan; 15.11.2017
comment
На самом деле это особенность баз данных nosql. Не стесняйтесь создавать отдельные таблицы. Это поможет управлять пропускной способностью для каждого стола и сэкономить ваши деньги. - person Dmitry Grinko; 15.11.2017
comment
Спасибо за предложение, Дмитрий, FYKI MongoDB поддерживает его. - person Narayanan Ramanathan; 16.11.2017