Получение массивов вложенной информации в схеме AppSync - PullRequest
0 голосов
/ 28 августа 2018

Я разработал довольно сложную цепочку преобразователей DynamoDB по запросу GraphQL AppSync. Что мне любопытно узнать, так это если бы я мог спроектировать это таким образом, чтобы потребовать меньше запросов DynamoDB.

Вот моя схема GraphQL:

type Tag {
    PartitionKey: ID!
    SortKey: ID!
    TagName: String!
    TagType: String
}

type Model {
    PartitionKey: ID!
    Name: String
    Version: Int
    FBX: String
    # ms since epoch
    CreatedAt: AWSTimestamp
    Description: String
    Tags: [String]
}

type Query {
    GetAllModels(count: Int, nextToken: String): PaginatedModels!
}

Это запрос, который я делаю:

query GetAllModels{
  GetAllModels {
    Models {    
        PartitionKey        
        Name
        Version
        CreatedAt
        Description
        Tags {
          TagName
          TagType
        }
    }
  }
}

Моя таблица DynamoDB настроена так:

PartionKey | SortKey       | TagName | TagType | ModelName | Description
Model-0    | Model-0       |                     ModelZero | Blah Blah   
Model-0    | Tag-Pine      |
Model-0    | Tag-Apple     |
Tag-Pine   | Tag-Pine      | Pine    | Tree
Tag-Apple  | Tag-Apple     | Apple   | Fruit

Так что в моих резольверах я иду:

  1. GetAllModels будет сканировать с двумя фильтрами. Один фильтр для PartitionKey начинается с 'Model-', а другой фильтр для SortKey начинается с 'Model-'. Это чтобы получить все модели.

  2. Далее в объекте модели присоединен определитель, прикрепленный к тегам. Это запрос с двумя выражениями. Один для PartitionKey = source.Parition и второй для SortKey begin_with 'Tag-', это возвращает мне все теги на модели.

  3. Далее в объекте Tag есть два резольвера. Один на TagName и другой на TagType. Они делают прямой GetItem, чтобы получить их соответствующее значение с PartitionKey = source.Sort и SortKey = source.SortKey, установленными в качестве ключей.

Таким образом, каждая отсканированная модель запускает еще 3 запроса к DynamoDB. Это просто кажется мне чрезмерным. Но я не вижу другого способа сделать это. Есть ли какой-нибудь способ получить и TagName, и TagType в одном запросе?

Есть ли лучший способ приблизиться к этому?

1 Ответ

0 голосов
/ 29 августа 2018

Я вижу несколько вещей, которые я бы лично изменил. Во-первых, я бы избегал вложенных операций сканирования DynamoDB. По крайней мере, один из них может быть заменен намного более быстрой операцией запроса. Во-вторых, я бы подумал переосмыслить, как вы храните данные. В настоящее время нет хорошего способа составить список объектов модели.

Почему нет хорошего способа перечислить объекты модели?

Если предположить, что у каждого объекта модели будет несколько тегов, то у вас будет таблица, которая редко заполняется объектами модели. то есть из 100 строк у вас может быть 20-50 моделей в зависимости от того, сколько тегов имеет средняя модель. В DynamoDB таблица разделяется на основе ключа секционирования, в результате чего строки, совместно использующие один и тот же ключ секционирования, хранятся рядом друг с другом для ускорения операций запроса. С вашей настройкой, где ключ разделения по сути является уникальным идентификатором одного объекта модели, это означает, что мы можем легко получить один объект модели. Вы также можете быстро получить теги для одного объекта, так как эти записи также находятся рядом.

Вопрос.

Операция сканирования DynamoDB просматривает каждый раздел по одному, считывает столько записей, сколько позволяет запрос limit или все из них, если limit достаточно велик, и затем только после чтения записей из отдельных разделов применяет выражение фильтра перед возвратом окончательного результата. Это означает, что вы можете запросить первые 10 моделей, но поскольку ограничение применяется до фильтра сканирования, вы вполне можете вернуть только 1 модель (если у этой модели было 9 или более тегов, которые исчерпали бы ограничение, пока DynamoDB считывал первый раздел). Это может показаться странным, если исходить из множества различных систем баз данных, и является важным соображением при проектировании.

Вот два решения для решения этой проблемы:

1. Храните модели в одной таблице и теги в другой.

Базы данных NoSQL, такие как DynamoDB, позволяют хранить много типов данных в одной таблице, но нет ничего плохого в их разделении. Традиционно бывает сложно работать с несколькими таблицами в базе данных NoSQL, в которой отсутствует операция соединения или что-то подобное, но, к счастью, мы можем использовать GraphQL, чтобы «объединить» данные для нас. При таком подходе таблица Model имеет один ключ раздела с именем "id", а ваш преобразователь GetAllModels все еще сканирует, но на этот раз в таблице модели. Таким образом, таблица не скудная, и вы получите 10 моделей, когда попросите 10 моделей. Таблица Tag должна иметь ключ раздела modelId и ключ сортировки tagId . После этого у вас будет преобразователь в поле Model.tags , который выполняет запрос к таблице Tag и ищет строки с modelId == $ ctx.source.id. .

Это, по сути, то, как @model и @connection работают в новом инструменте преобразования graphql, запущенном как часть усиливающего кли. Вы можете увидеть больше здесь, хотя документы на момент написания находятся в стадии совершенствования. https://aws -amplify.github.io / усиливать-JS / СМИ / api_guide

2. Храните модели и теги в одной таблице, но изменяйте структуру ключа.

Этот подход работает, если вы можете с уверенностью сказать, что у вас будет менее 10 ГБ данных на тип данных (например, Модель и тег). Для этого подхода у вас есть одна таблица с ключом PartitionKey Тип и ключом сортировки id . Когда вы создаете объекты, вы создаете их с Type , например, "Tag" или "Model" и т. Д. И уникальным id (например, uuid). Чтобы вывести список объектов одного типа, вы выполняете операцию запроса DynamoDB над ключом раздела типа для перечисления, например. «Метка» или «Модель». Затем вы можете использовать GSI для эффективного поиска связанных объектов. В вашем случае вы должны хранить «modelId» для каждого Tag объекта. Затем вы создадите GSI, используя «modelId» в качестве ключа раздела. Чтобы вывести список всех тегов для данной модели, вы можете выполнить операцию запроса DynamoDB для этого GSI.

Я уверен, что есть еще много способов сделать это, но, надеюсь, это поможет указать правильное направление.

...