Вопрос или проблема
Я хочу смоделировать запрос SELECT * FROM TABLE WHERE ID IN {LIST_OF_IDS}
. Я знаю, что использую базу данных NoSQL (dynamoDB), но у меня есть индекс на поле, по которому я хочу выполнить этот запрос. В основном я хочу получить все посты от пользователя, где userID (индексный столбец) находится в данном списке.
Я использую Amplify в качестве управляемого бэкенда и GraphQL в качестве API. Я знаю, что нет ключевого слова IN
для использования в GraphQL (по крайней мере, в APPSYNC). Я пытался создать пользовательский резолвер на основе шаблона, предоставленного AWS, вот так:
import { util } from '@aws-appsync/utils';
/**
* Получает элементы из таблиц DynamoDB партиями с предоставленными ключами `id`
* @param {import('@aws-appsync/utils').Context} ctx контекст
* @returns {import('@aws-appsync/utils').DynamoDBBatchGetItemRequest} запрос
*/
export function request(ctx) {
return {
operation: 'BatchGetItem',
tables: {
Posts: {
keys: ctx.args.ids.map((id) => util.dynamodb.toMapValues({ id })),
consistentRead: true,
},
},
};
}
/**
* Возвращает элементы таблицы BatchGetItem
* @param {import('@aws-appsync/utils').Context} ctx контекст
* @returns {[*]} элементы
*/
export function response(ctx) {
if (ctx.error) {
util.error(ctx.error.message, ctx.error.type);
}
return ctx.result.data.Posts;
}
Но это, похоже, не работает. Я также хотел бы избежать выполнения запроса для каждого пользователя в списке, чтобы получить посты. Буду признателен за любую помощь, а также если у вас есть другое архитектурное решение/предложение для решения этой проблемы, я слушаю!
Ответ или решение
Для решения вашей задачи по эмуляции оператора IN
в базе данных NoSQL (в данном случае DynamoDB) при использовании GraphQL и Amplify, действительно можно использовать функцию BatchGetItem
, как вы уже пробовали. Но прежде всего, убедитесь, что вы правильно настроили элемент в таблице и определили индекс для поля userID
. Давайте разберемся с вашим кодом и оптимизируем решение.
Пример opgelostия
Шаг 1: Настройка таблицы и индексов
Убедитесь, что у вас есть таблица, в которой хранится информация о постах, с соответствующими ключами и индексами. Допустим, у вас есть таблица Posts
с ключом id
и индексом userID
.
Шаг 2: Создание кастомного резолвера
Используйте ваш текущий код, но убедитесь, что вы обрабатываете данные правильно. Вот улучшенный вариант вашего кода:
import { util } from '@aws-appsync/utils';
/**
* Получает элементы из таблицы DynamoDB в пакетах с заданными ключами `ids`
* @param {import('@aws-appsync/utils').Context} ctx контекст
* @returns {import('@aws-appsync/utils').DynamoDBBatchGetItemRequest} запрос
*/
export function request(ctx) {
return {
operation: 'BatchGetItem',
tables: {
Posts: {
keys: ctx.args.ids.map(id => util.dynamodb.toMapValues({ id })),
consistentRead: true,
},
},
};
}
/**
* Возвращает элементы из BatchGetItem
* @param {import('@aws-appsync/utils').Context} ctx контекст
* @returns {[*]} элементы
*/
export function response(ctx) {
if (ctx.error) {
util.error(ctx.error.message, ctx.error.type);
}
return ctx.result.data.Posts;
}
Шаг 3: Использование резолвера в GraphQL запросе
Теперь вы можете использовать этот резолвер в вашем GraphQL запросе. Например:
query GetPosts($ids: [ID!]!) {
getPosts(ids: $ids) {
id
userID
content
createdAt
}
}
Шаг 4: Передача данных
Не забудьте передать массив ids
при вызове этого запроса из вашего фронтенда. Например:
const postIds = ["id1", "id2", "id3"];
const result = await API.graphql(graphqlOperation(getPosts, { ids: postIds }));
Альтернативный подход
Если вы хотите избежать использования BatchGetItem
, можно рассмотреть использование Query
с индексами. Однако, это будет означать, что требуется выполнять множество запросов, что может оказаться менее эффективным, чем BatchGetItem
.
Заключение
Итак, используя метод BatchGetItem
в вашем кастомном резолвере, вы сможете эффективно получить данные по нескольким ids
без выполнения отдельных запросов для каждого пользователя. Убедитесь, что ваш индекс правильно настроен и что все ключи уникальны для успешного получения данных.
Если у вас возникнут дополнительные вопросы или потребуется помощь с реализацией, не стесняйтесь обращаться!