Я действительно играл с AppSync / noSQL с тех пор, как обнаружил его. Как разработчику мне нравится контролировать свои инструменты, и у меня есть личная цель - попытаться понять, почему и как вещи созданы для использования. AppSync предоставляет удобный простой инструмент для тестирования и изучения. Он также обеспечивает хороший уровень документированного усложнения, что позволяет мне думать по-разному.
Это стремление к открытиям привело меня к еще одной кладовой информации в иногда огромных документах Amazon. Начиная с этого видео:
Даже не имея глубоких практических знаний о реляционных базах данных, я нашел это видео очень кратким и пояснительным. Один из основных выводов заключался в том, что я, возможно, думал о вещах неправильно.
«Вам следует поддерживать как можно меньше таблиц в приложении DynamoDB. Для большинства хорошо разработанных приложений требуется только одна таблица ».
Почему это так сильно выделялось? Ну, я недавно написал статью о добавлении нескольких элементов в несколько баз данных DynamoDB одновременно, найденную здесь. Это было отличное исследование пакетных инструментов и преобразователей кросс-таблиц, но я обнаружил, что задаю несколько разных вопросов.
- Если мне нужно выполнить поиск на основе значения в таблице A, как мне вернуть информацию из таблицы B с помощью GraphQL?
- Если мне нужно выполнить поиск по одному запросу на основе двух полей, которые используются в таблицах, почему я не использую одну таблицу? Т.е. В таблице A есть поле «заголовок», а в таблице B - поле «заголовок».
- Есть ли способ создавать и возвращать разные аспекты одной таблицы в одних и тех же запросах graphQL?
Принятие решения изучить эти вопросы сорвало рабочий процесс моего проекта, но в целом это принесло пользу. Итак, вот окончательный результат последнего глубокого погружения в управление данными DynamoDB + GraphQL +.
Я буду продолжать использовать Рецепт в качестве своего имитационного объекта.
Организация данных
В модели с несколькими столами у меня была таблица для каждой части рецепта. Рецепт, элементы рецепта и ингредиенты.
При переходе к модели с одной таблицей моя структура данных сильно изменилась. Примечание. Это не окончательная модель данных. Скорее всего, я внесу изменения в ключ первичного раздела. Я также избегал сокращений для удобочитаемости.
Теперь я использую один первичный ключ раздела для всех частей рецепта, используя первичный ключ сортировки, чтобы различать разные части.
У рецепта есть идентификатор:
87971.
Вся высокоуровневая информация о рецепте хранится в виде идентификатора:
recipe87971: info1.
Каждый элемент хранится в виде идентификатора:
recipe87971: element1.
Каждый ингредиент хранится в виде идентификатора относительно его родительского элемента:
recipe87971: element1: component1.
Все части рецепта могут быть немедленно загружены, зная только идентификатор родительского рецепта! Это отличается от поиска по нескольким таблицам тем, что я выполняю один запрос на чтение. Поскольку все они расположены рядом друг с другом, гипотетически это могло бы использовать преимущества Amazon.
Определение схемы
Определение схемы не меняется слишком сильно между моделями. Одно небольшое изменение, которое я заметил, заключается в том, что вложенные элементы, живущие все в одной таблице, теперь должны иметь ссылку в родительском объекте, который будет вызван. Таким образом, мой тип рецепта выглядит следующим образом:
type Recipe { id: ID! type: ID! title: String! category: String dbtype: String status: String elements: [Element] ingredients: [Ingredient] }
- В моей предыдущей итерации
ingredients
жил только с типом Element.
Большим изменением в этом определении схемы является возврат запросов. Именно здесь я сильнее ощущаю присутствие GraphQL. Допустим, я просматриваю список названий рецептов + краткое описание, а затем нахожу рецепт, который хочу проверить. Пользователь может щелкнуть элемент, а затем, используя его идентификатор, мы можем запросить и скомпилировать данные нужным образом.
type RecipeBuild { id: ID category: String elements: [Recipe] title: String type: String status: String }
Ингредиенты не нужно открывать напрямую, потому что с этим можно справиться в нашем преобразователе. Это работает, потому что мы не возвращаем ни одного элемента при поиске по идентификатору рецепта. Мы находим детали, которые можем потреблять по своему желанию.
Шаблоны картографии
Теперь, когда у нас есть детали, нам просто нужно определить, как мы будем с ними работать.
Наш шаблон запроса остается простым, запрос по идентификатору. Если в ответ не было внесено никаких изменений, мы получили бы базовый список с элементом массива для каждого элемента с идентификатором.
Но мы этого не хотим. Для внешнего интерфейса нам нужно убедиться, что данные организованы для визуализации. Информация высокого уровня отделена от вложенных элементов. Это позволит нам map
по каждому элементу, а также по каждому ингредиенту, содержащемуся в элементах. В конечном итоге было бы неплохо что-то вроде этого:
Основной ответ на запрос - это плоский список, но весь смысл засучить рукава и копаться в бэкэнде состоит в том, чтобы мне не приходилось делать это во фронтэнде. Итак, немного поработав и немного поработав на Java, я получил этот симпатичный маленький компилятор данных.
Происходит несколько вещей.
- Каждый элемент просматривается и, в зависимости от его типа, помещается в массив или сохраняется как переменная.
- Информация высокого уровня возвращается как атрибут карты
- Элементам предоставляется их собственный массив, который будет возвращен как атрибут возвращаемой карты.
- Ингредиенты хранятся в собственном массиве для дальнейшей итерации.
- Ингредиенты, основанные на их
elementId
, затем сохраняются в правильном элементе для повторения позже. Примечание. Вы заметите, что мы не отображаем массив Ingredients напрямую на карте. Это потому, что это карта и работает как JSON, поэтому нам не нужно.
Этот шаблон сопоставления ответов возвращает следующее при поиске определенного идентификатора рецепта блинов:
Не потрепать а! Это в дополнение к пакетному добавлению записей db должно поддерживать довольно низкую потребляемую емкость чтения / записи. Однако я не смогу проверить это, пока не интегрирую эту новую модель данных в мой клиент Apollo / React. Скорее всего, я напишу об этом в следующий раз!