Flutter
GraphQL
Реляционные мутации данных в Flutter с GraphQL
21 мин
хранение реляционных данных с использованием graphql введение в последних двух уроках мы выполняли запросы и мутации graphql в базе данных back4app из нашего проекта flutter app мы используем https //pub dev/packages/graphql flutter/install в качестве нашего клиента graphql, так как это очень надежный и широко используемый проект для этих уроков мы использовали очень простую модель данных с наиболее распространенными типами для наших классов back4app — это гибкая платформа, которая позволяет вам создавать, хранить и запрашивать реляционные данные в этом уроке мы углубимся в эту возможность, показывая вам, как использовать отношения и указатели при сохранении и запросе реляционных данных на бэкенде back4app также мы исследуем другие типы данных, которые предлагает back4app, такие как geopointer и datetime цели в конце этой статьи вы сможете создавать/обновлять и удалять реляционные данные (используя указатели и отношения) создавать/обновлять geopointers создавать/обновлять дату и время предварительные условия чтобы завершить этот учебник, вам потребуется убедитесь, что вы прочитали предыдущие два руководства https //www back4app com/docs/flutter/graphql/flutter graphql project with source code download и https //www back4app com/docs/flutter/graphql/flutter crud app example скачайте файл проекта с https //github com/templates back4app/flutter graphql/tree/complex mutations который включает в себя предыдущий код, а также новый интерфейс, который вам понадобится откройте загруженный проект в ide flutter, таком как vs code или android studio аккаунт back4app, который можно создать https //www back4app com/ подключите ваш учебник к back4app в соответствии с предыдущими учебниками https //www back4app com/docs/flutter/graphql/flutter graphql project with source code download 1 настройка бэкенда в нашем https //www back4app com/docs/flutter/flutter crud app example наша модель данных была очень простой, с единственным классом язык теперь мы собираемся сделать ее более сложной, добавив 2 новых класса и связав их с языком основатель с форматом название столбца описание имя имя основателя языка название столбца описание имя имя владельца компании дата владения дата получения права собственности компанией штаб квартира местоположение штаб квартиры компании мы создадим отношение один к одному между классом language и классом founder с использованием указателей parse, которые будут указывать на основателя конкретного языка затем мы создадим отношение один ко многим между классом language и классом ownership с использованием отношений parse, которые будут указывать, какая организация/компания владела языком, их штаб квартира и дата, когда они приобрели право собственности на язык модель данных будет выглядеть так прежде чем перейти к нашему приложению, давайте создадим классы и данные в нашем бэкэнде, которые нам понадобятся перейдите в ваше приложение back4app, а затем в graphql playground используя приведенную ниже мутацию, создайте класс founder , где мы будем хранить имена основателей языков 1 mutation createclass { 2 createclass(input { 3 name "founder" 4 schemafields { 5 addstrings \[{name "name"}] 6 } 7 }){ 8 class{ 9 schemafields{ 10 name 11 typename 12 } 13 } 14 } 15 } теперь давайте заполним наш класс именами основателей в следующих шагах мы будем использовать эти данные для создания новых языков, указывающих на класс основателя используйте мутацию ниже в back4app graphql playground, чтобы создать ваших основателей 1 mutation createobject{ 2 createfounder(input {fields {name "james gosling"}}){ 3 founder{ 4 id 5 name 6 } 7 } 8 } здесь мы ввели имя основателя языка программирования java вы можете сделать то же самое и для других, но сейчас этого достаточно для нашего руководства давайте создадим класс ownership , в котором мы будем хранить право собственности на язык, дату основания (дата время) и местоположение штаб квартиры владельца (geopointer) позже мы создадим связь между классом язык и право собственности продолжайте, запустив код ниже для создания класса 1 mutation createclass { 2 createclass(input { 3 name "ownership" 4 schemafields { 5 addstrings \[{name "name"}] 6 adddates \[{name "date owned"}] 7 } 8 }){ 9 class{ 10 schemafields{ 11 name 12 typename 13 } 14 } 15 } 16 } теперь заполните класс ownership с помощью следующих мутаций 1 mutation createobject{ 2 createownership(input {fields {name "sun microsystems"}}){ 3 ownership{ 4 id 5 name 6 } 7 } 8 } 1 mutation createobject{ 2 createownership(input {fields {name "oracle"}}){ 3 ownership{ 4 id 5 name 6 } 7 } 8 } теперь обновите страницу, перейдите к ownership ownership классу в браузере базы данных выберите добавить новый столбец в правом верхнем углу выберите geopoint из первого выпадающего списка и назовите его headquarters во втором текстовом поле оставьте все как есть и нажмите кнопку добавить столбец затем перейдите в ваш язык язык класс в браузере баз данных давайте добавим связи к право собственности право собственности и основатель основатель классам нажмите на добавить новый столбец и затем выберите тип данных указатель и целевой класс основатель основатель дайте столбцу то же имя основатель затем нажмите добавить столбец теперь повторите этот процесс, добавив новый столбец под названием право собственности, используя тип данных связь и выбрав класс право собственности право собственности теперь у вас есть ваша модель данных, готовая к использованию в вашем приложении flutter, чтобы начать сохранять и обновлять данные 2 создание/добавление и удаление указателей теперь вам нужно скачать шаблон кода проекта из нашего https //github com/templates back4app/flutter graphql/tree/complex mutations и открыть его в вашей ide чтобы подключить ваш проект к back4app, перейдите в graphql playground и скопируйте ключи и url api, как показано на изображении ниже теперь вставьте их в constants dart constants dart и запустите ваш проект запустите приложение в вашем эмуляторе перейдите к m плавающей кнопке внизу это приведет нас на страницу, где мы выполняли простые мутации здесь вы найдете дополнительную плавающую кнопку действия cm это кнопка, которую мы будем использовать для выполнения наших сложных мутаций graphql нажмите на кнопку cm , и вы увидите еще четыре кнопки, по одной для каждой операции, которую мы собираемся выполнить в этом руководстве теперь откройте файл databaseutils dart databaseutils dart и прокрутите вниз до метода addpointers() addpointers() здесь мы добавим логику для добавления указателей мы собираемся указать джеймса гослинга как основателя языка java поэтому сначала вам нужно перейти в ваш бэкенд back4app и скопировать как objectid objectid , так и основателя (джеймса гослинга) и языка (java) обновление/создание указателя на данные перейдите к нашему приложению внутри databaseutils dart databaseutils dart и внутри метода addpointers() addpointers() инициализируйте string addpointerquery string addpointerquery где мы назначим запрос graphql для добавления указателей следующим образом 1 string addpointerquery= 2 ''' 3 mutation addpointer(\\$languageid id!, \\$founderid updatelanguagefieldsinput! ){ 4 updatelanguage(input {id \\$languageid, fields \\$founderid}) 5 { 6 language{ 7 objectid 8 } 9 } 10 } 11 '''; и инициализируйте финальную переменную финальную переменную для назначения переменных, обратите внимание, что мы берем rowobjectid rowobjectid и pointersid pointersid в качестве параметров, где rowobjectid rowobjectid идентификатор объекта строки, откуда мы будем указывать pointersid pointersid идентификатор объекта строки, на которую будет указывать итак, объявите переменную переменную как 1 final variable={ 2 "userid" rowobjectid, 3 "founderid" { 4 "founder" { 5 "link" pointersid 6 } 7 } 8 }; теперь, как в последнем руководстве, мы инициализируем graphqlclient graphqlclient и отправим запрос с помощью queryoptions() queryoptions() и вернем его экземпляр с queryresults() queryresults() 1 graphqlconfiguration configuration = graphqlconfiguration(); 2 graphqlclient client = configuration clienttoquery(); 3 4 queryresult queryresult = await client query( 5 queryoptions(documentnode gql(addpointerquery), variables variable), 6 ); 7 return queryresult; вот как должен выглядеть ваш addpointers() addpointers() метод 1 future\<queryresult> addpointers(string rowobjectid, string pointersid) async{ 2 print('addpointers'); 3 //code for add/update pointers 4 string addpointerquery= 5 ''' 6 mutation addpointer(\\$languageid id!, \\$founderid updatelanguagefieldsinput! ){ 7 updatelanguage(input {id \\$languageid, fields \\$founderid}) 8 { 9 language{ 10 objectid 11 } 12 } 13 } 14 '''; 15 final variable={ 16 "userid" rowobjectid, 17 "founderid" { 18 "founder" { 19 "link" pointersid 20 } 21 } 22 }; 23 graphqlconfiguration configuration = graphqlconfiguration(); 24 graphqlclient client = configuration clienttoquery(); 25 26 queryresult queryresult = await client query( 27 queryoptions(documentnode gql(addpointerquery), variables variable), 28 ); 29 return queryresult; 30 } теперь перезапустите ваше приложение, перейдите к cm кнопке на странице мутации, а затем нажмите кнопку добавить указатели здесь введите строку objectid objectid где указатель должен быть добавлен в первом текстовом поле и objectid objectid строки, на которую он будет указывать, во втором текстовом поле, а затем нажмите готово теперь проверьте вашу панель управления, и вы должны увидеть связь в колонке основатель вы можете нажать на нее, и это перенесет вас к строке, указывающей на класс основатель удаление указателя на данные теперь перейдите к методу deletepointers() deletepointers() , где мы напишем логику для удаления отношений чтобы удалить отношения, вам просто нужно внести небольшие изменения в запрос выше, а именно, в переменных просто замените "link" "link" на "remove" "remove" итак, после инициализации финальной переменной финальной переменной это будет 1 final variable={ 2 "languageid" rowobjectid, 3 "founderid" { 4 "founder" { 5 "remove" pointersid 6 } 7 } 8 }; все остальное будет выглядеть точно так же, как addpointers() addpointers() итак, ваш deletepointers() deletepointers() метод выглядит так 1 future\<queryresult> deletepointers(string rowobjectid, string pointersid) async{ 2 print('deletepointers'); 3 //code for delete pointers 4 string removepointersquery= 5 ''' 6 mutation addpointer(\\$languageid id!, \\$founderid updatelanguagefieldsinput! ){ 7 updatelanguage(input {id \\$languageid, fields \\$founderid}) 8 { 9 language{ 10 objectid 11 } 12 } 13 } 14 '''; 15 final variable={ 16 "languageid" rowobjectid, 17 "founderid" { 18 "founder" { 19 "remove" pointersid 20 } 21 } 22 }; 23 graphqlconfiguration configuration = graphqlconfiguration(); 24 graphqlclient client = configuration clienttoquery(); 25 26 queryresult queryresult = await client query( 27 queryoptions(documentnode gql(removepointersquery), variables variable), 28 ); 29 return queryresult; 30 31 } теперь вы можете перейти на свою панель управления back4app и увидеть, что столбец основателя конкретной строки был удален 3 создание/добавление и удаление данных даты и времени если вы помните, мы создали класс ownership ранее в шаг 1 и сохранили в него некоторые данные это названия компаний, которые владели языком программирования java итак, сначала давайте введем даты, когда они приобрели право собственности давайте перейдем к databaseutils dart databaseutils dart и создадим или прокрутим вниз к adddatetime() adddatetime() функции здесь мы напишем логику для добавления типа данных дата время в наш класс инициализируйте string adddatetimequery string adddatetimequery и присвойте ему запрос для создания данных даты и времени 1 string adddatetimequery= 2 ''' 3 mutation addtime(\\$rowid id!,\\$dateowned date!){ 4 updateownership(input {id \\$rowid, fields {date owned \\$dateowned}}) 5 { 6 ownership{ 7 objectid 8 } 9 } 10 } 11 '''; а финальная переменная финальная переменная как 1 final variable={ 2 "rowid" rowobjectid, 3 "dateowned" datetime 4 }; теперь инициализируйте graphqlclient graphqlclient и передайте запрос через queryoption() queryoption() вот как будет выглядеть ваша функция 1 future\<queryresult> adddatetime(string rowobjectid, string datetime) async{ 2 print('adddatetime'); 3 //code for add/update date time 4 string adddatetimequery= 5 ''' 6 mutation addtime(\\$rowid id!,\\$dateowned date!){ 7 updateownership(input {id \\$rowid, fields {date owned \\$dateowned}}) 8 { 9 ownership{ 10 objectid 11 } 12 } 13 } 14 '''; 15 final variable={ 16 "rowid" rowobjectid, 17 "dateowned" datetime 18 }; 19 graphqlconfiguration configuration = graphqlconfiguration(); 20 graphqlclient client = configuration clienttoquery(); 21 queryresult queryresult = await client query( 22 queryoptions(documentnode gql(adddatetimequery), variables variable), 23 ); 24 return queryresult; 25 } теперь hot restart приложение и запишите objectid строки, содержащей sun microsystems в name столбце нажмите кнопку add date time теперь введите objectid из первого текстового поля и “02 24 1982” в формате mm dd yyyy в день, когда java была опубликована, и нажмите кнопку done перейдите к вашему back4app бэкенду, и вы увидите дату в формате 24 feb 1982 at 00 00 00 utc что означает, что он определил тип данных как тип данных дата время аналогично, вы можете добавить “01 27 2010” для date owned для oracle 4 добавление/обновление данных geopointer давайте добавим данные geopointer для определения штаб квартир компаний из таблицы ownership перейдите к файлу database utils dart database utils dart и прокрутите вниз до функции addgeopointers() addgeopointers() теперь инициализируйте string addgeopointers string addgeopointers и присвойте соответствующий запрос 1 string addgeopointers= 2 ''' 3 mutation addgeopointer(\\$objectid id!,\\$latitude float!,\\$longitude float!){ 4 updateownership(input {id \\$objectid, fields { headquarters {latitude \\$latitude, longitude \\$longitude}}}) 5 { 6 ownership{ 7 objectid 8 } 9 } 10 } 11 '''; и финальная переменная финальная переменная как 1 final variable={ 2 "objectid" rowobjectid, 3 "latitude" double parse(latitude), 4 "longitude" double parse(longitude), 5 }; поскольку широта широта и долгота долгота являются значениями типа double, нам нужно преобразовать их из string в double перед отправкой инициализируйте grapqlclient grapqlclient и передайте запрос с помощью queryoption() queryoption() вот как будет выглядеть ваша функция addgeopointers() addgeopointers() 1 future\<queryresult> addgeopointers(string rowobjectid, string latitude, string longitude) async{ 2 print('add geopointers'); 3 //code for add/update geopointers 4 string addgeopointers= 5 ''' 6 mutation addgeopointer(\\$objectid id!,\\$latitude float!,\\$longitude float!){ 7 updateownership(input {id \\$objectid, fields { headquarters {latitude \\$latitude, longitude \\$longitude}}}) 8 { 9 ownership{ 10 objectid 11 } 12 } 13 } 14 '''; 15 final variable={ 16 "objectid" rowobjectid, 17 "latitude" double parse(latitude), 18 "longitude" double parse(longitude), 19 }; 20 graphqlconfiguration configuration = graphqlconfiguration(); 21 graphqlclient client = configuration clienttoquery(); 22 queryresult queryresult = await client query( 23 queryoptions(documentnode gql(addgeopointers), variables variable), 24 ); 25 return queryresult; 26 } горячий перезапуск вашего приложения и выберите кнопку добавить geopointers введите 37 35 37 35 в первом текстовом поле и 121 95 121 95 во втором текстовом поле введите objectid строки с sun microsystems как название и нажмите готово теперь перейдите к вашему back4app backend, и вы увидите (37 35, 121 95) которые являются координатами штаб квартиры и указывают, что они идентифицируются как geopointers 5 добавление/обновление и удаление связи в указателях мы можем указывать только одну строку, но с помощью связей мы можем установить связь с несколькими строками итак, давайте создадим связь нашей языковой таблицы с этими двумя строками для право собственности на java язык добавление/обновление связи перейдите к database utils dart database utils dart файлу и перейдите к addrelation() addrelation() функции для написания логики инициализируйте string addrelationquery string addrelationquery и присвойте запрос для связи следующим образом 1 string addrelationquery= 2 ''' 3 mutation addrelation(\\$objectid id!, \\$relationid ownershiprelationinput){ 4 updatelanguage(input {id \\$objectid, fields {ownership \\$relationid}}) 5 { 6 language{ 7 objectid 8 } 9 } 10 } 11 '''; и финальная переменная финальная переменная будет 1 final variable= { 2 "objectid" objectid, 3 "relationid" relationid 4 }; итак, после инициализации graphqlclient graphqlclient и передачи запроса, как раньше, вот как будет выглядеть ваш database utils dart database utils dart 1 future\<queryresult> addrelation(string rowobjectid, string relationid) async{ 2 //code for add/update relation 3 print('addrelation'); 4 string addrelationquery= 5 ''' 6 mutation addrelation(\\$objectid id!, \\$relationid ownershiprelationinput){ 7 updatelanguage(input {id \\$objectid, fields {ownership \\$relationid}}) 8 { 9 language{ 10 objectid 11 } 12 } 13 } 14 '''; 15 final variable= { 16 "objectid" rowobjectid, 17 "relationid" { 18 "add" relationid 19 } 20 }; 21 graphqlconfiguration configuration = graphqlconfiguration(); 22 graphqlclient client = configuration clienttoquery(); 23 queryresult queryresult = await client query( 24 queryoptions(documentnode gql(addrelationquery), variables variable), 25 ); 26 print(queryresult); 27 return queryresult; 28 } успех ваше приложение наконец то сохранило реляционные, временные и geopointers данные на back4app! заключение в этом руководстве мы узнали, как хранить реляционные данные на back4app, используя graphql в проекте flutter app также мы работали с другими мутациями graphql, такими как geopointers и datetime, создавая, обновляя и удаляя данные в следующем уроке мы углубимся в запросы к нашему приложению flutter это руководство было написано асимом джунаином из https //www back4app com/partners/software development company