Flutter
...
Data Queries
Relational Queries
12 min
parse relational query in flutter introduction you’ve already seen how to store relational data objects using theparse pointer and parse relations data types you’ve learned that on parse it is possible to use any parseobject as a value in other parseobject, establishing a relation between them internally, the parse framework will store the referred to object in just one place to maintain consistency that can give you extra power when building and running complex queries also, you’ve already learned how to use a querybuilder with get can retrieve a single parseobject from back4app there are many other ways to retrieve data with querybuilder in this guide, you will ding deep into the querybuilder class and see methods you can use to build relational queries you will use a simple database class with some mocked data to perform the queries using flutter on back4app prerequisites to complete this tutorial, you will need android studio https //developer android com/studio or vs code installed (with plugins dart and flutter) an app created on back4app note follow the new parse app tutorial to learn how to create a parse app on back4app an flutter app connected to back4app note follow the install parse sdk on flutter project to create an flutter project connected to back4app a device (or virtual device) running android or ios goal query relational data stored on back4app from a flutter app 1 understanding the querybuilder class any parse query operation uses the querybuilder object type, which will help you retrieve specific data from your database throughout your app to create a new querybuilder, you need to pass as a parameter the desired parseobject subclass, which is the one that will contain your query results it is crucial to know that a querybuilder will only resolve after calling a retrieve method query, so a query can be set up and several modifiers can be chained before actually being called 1 // this will create your query 2 querybuilder\<parseobject> querybook = 3 querybuilder\<parseobject>(parseobject('book')); 4 5 // the query will resolve only after calling this method 6 final parseresponse apiresponse = await querybook query(); 7	 8 if (apiresponse success && apiresponse results != null) { 9 10 } else { 11 12 } you can read more about the querybuilder class here at the official documentation using the javascript console on back4app inside your back4app application’s dashboard, you will find a very useful api console in which you can run javascript code directly in this guide you will use to store data objects in back4app on your app main dashboard go to core >api console >javascript 2 save data on back4app to run the queries on this guide you’ll need first to populate your app with some data the classes are author , book , publisher and bookstore which book has a 1\ n relation with publisher and n\ n with author , and bookstore has an n\ n relation with book here is the parse object classes creation code, so go ahead and run it in your api console 1 // add objects and create tables 2 // authors 3 const authora = new parse object('author'); 4 authora set('name', 'aaron writer'); 5 await authora save(); 6 7 const authorb = new parse object('author'); 8 authorb set('name', 'beatrice novelist'); 9 await authorb save(); 10 11 const authorc = new parse object('author'); 12 authorc set('name', 'casey columnist'); 13 await authorc save(); 14 15 const authord = new parse object('author'); 16 authord set('name', 'gary stur'); 17 await authord save(); 18 19 const authore = new parse object('author'); 20 authore set('name', 'mary sue'); 21 await authore save(); 22 23 // publishers 24 const publishera = new parse object('publisher'); 25 publishera set('name', 'acacia publishings'); 26 await publishera save(); 27 28 const publisherb = new parse object('publisher'); 29 publisherb set('name', 'birch distributions'); 30 await publisherb save(); 31 32 const publisherc = new parse object('publisher'); 33 publisherc set('name', 'acacia distributions'); 34 await publisherc save(); 35 36 37 // books 38 const booka = new parse object('book'); 39 booka set('title', 'a love story'); 40 booka set('publisher', publishera); 41 booka set('publishingdate', new date('05/07/1998')); 42 const bookarelation = booka relation("authors"); 43 bookarelation add(authora); 44 await booka save(); 45 46 const bookb = new parse object('book'); 47 bookb set('title', 'benevolent elves'); 48 bookb set('publisher', publisherb); 49 bookb set('publishingdate', new date('11/31/2008')); 50 const bookbrelation = bookb relation("authors"); 51 bookbrelation add(authorb); 52 await bookb save(); 53 54 const bookc = new parse object('book'); 55 bookc set('title', 'can you believe it?'); 56 bookc set('publisher', publisherb); 57 bookc set('publishingdate', new date('08/21/2018')); 58 const bookcrelation = bookc relation("authors"); 59 bookcrelation add(authora); 60 bookcrelation add(authorc); 61 await bookc save(); 62 63 // bookstore 64 const bookstorea = new parse object('bookstore'); 65 bookstorea set('name', 'books of love'); 66 const bookstorearelation = bookstorea relation("books"); 67 bookstorearelation add(booka); 68 await bookstorea save(); 69 70 const bookstoreb = new parse object('bookstore'); 71 bookstoreb set('name', 'fantasy books'); 72 const bookstorebrelation = bookstoreb relation("books"); 73 bookstorebrelation add(bookb); 74 await bookstoreb save(); 75 76 const bookstorec = new parse object('bookstore'); 77 bookstorec set('name', 'general books'); 78 const bookstorecrelation = bookstorec relation("books"); 79 bookstorecrelation add(booka); 80 bookstorecrelation add(bookc); 81 await bookstorec save(); 82 83 console log('success'); after running this code, you should now have a author, publisher, book and bookstore class in your database your new class should look like this let’s now take a look at examples from every querybuilder method, along with brief explanations on what they do 3 query the data now that you have a populated class, we can now perform some relational queries now that you have populated all the classes, we can now perform some relational queries in it let’s begin by filtering book results by the publisher, searching for the ones that belong to the publisher “acacia publishings” (or “publisher a”) with relational pointer using the basic whereequalto method 1 // get publishera object 2 final querybuilder\<parseobject> publisherquerya = 3 querybuilder\<parseobject>(parseobject('publisher')) 4 whereequalto('name', 'acacia publishings'); 5 6 final parseresponse publisherresponse = await publisherquerya query(); 7 if (!publisherresponse success) { 8 return; 9 } 10 final publishera = publisherresponse results? first as parseobject; 11 12 // query books with publishera 13 final querybuilder\<parseobject> bookquery = 14 querybuilder\<parseobject>(parseobject('book')) 15 whereequalto('publisher', publishera); 16 17 final parseresponse bookresponse = await bookquery query(); 18 if (!bookresponse success) { 19 return; 20 } 21 22 for (var book in bookresponse results as list\<parseobject>) { 23 print(book get('title')); 24 } let’s now query which bookstore objects contain book objects with publishing date greater than 01/01/2010, using an inner query with the wheregreaterthan method and then the wherematchesquery method 1 // create inner book query 2 final querybuilder\<parseobject> bookquery = 3 querybuilder\<parseobject>(parseobject('book')) 4 wheregreaterthan('publishingdate', datetime(2010, 01, 01)); 5 6 // query bookstore using inner book query 7 final querybuilder\<parseobject> bookstorequery = 8 querybuilder\<parseobject>(parseobject('bookstore')) 9 wherematchesquery('books', bookquery); 10 11 final parseresponse bookstoreresponse = await bookstorequery query(); 12 if (!bookstoreresponse success) { 13 return; 14 } 15 16 for (var b in bookstoreresponse results as list\<parseobject>) { 17 print(b get('name')); 18 } let’s now create another query, looking for authors that are relation with the book can you believe it ?, using whererelatedto 1 // get book object 2 final querybuilder\<parseobject> bookquery = 3 querybuilder\<parseobject>(parseobject('book')) 4 whereequalto('title', 'can you believe it?'); 5 6 final parseresponse bookresponse = await bookquery query(); 7 if (!bookresponse success) { 8 return; 9 } 10 11 final book = bookresponse results? first as parseobject; 12 13 // get author with relation with book can you believe it? 14 final querybuilder\<parseobject> authorsquery = 15 querybuilder\<parseobject>(parseobject('author')) 16 whererelatedto('authors', 'book', book objectid!); 17 18 final parseresponse authorresponse = await authorsquery query(); 19 20 // let's show the results 21 if (authorresponse success && authorresponse results != null) { 22 for (var a in authorresponse results! as list\<parseobject>) { 23 print(a get('name')); 24 } 25 } 4 query from flutter let’s now use our example queries inside a flutter app, with a simple interface having a list showing results and also 3 buttons for calling the queries open your flutter project, go to the main dart file, clean up all the code, and replace it with 1 import 'package\ flutter/cupertino dart'; 2 import 'package\ flutter/material dart'; 3 import 'package\ parse server sdk flutter/parse server sdk dart'; 4 5 void main() async { 6 widgetsflutterbinding ensureinitialized(); 7 8 final keyapplicationid = 'your app id here'; 9 final keyclientkey = 'your client key here'; 10 final keyparseserverurl = 'https //parseapi back4app com'; 11 12 await parse() initialize(keyapplicationid, keyparseserverurl, 13 clientkey keyclientkey, debug true); 14 15 runapp(materialapp( 16 title 'flutter geopoint', 17 debugshowcheckedmodebanner false, 18 home homepage(), 19 )); 20 } 21 22 class homepage extends statefulwidget { 23 @override 24 homepagestate createstate() => homepagestate(); 25 } 26 27 class homepagestate extends state\<homepage> { 28 list\<parseobject> results = \<parseobject>\[]; 29 double selecteddistance = 3000; 30 31 void doquerypointer() async { 32 // get publishera object 33 final querybuilder\<parseobject> publisherquerya = 34 querybuilder\<parseobject>(parseobject('publisher')) 35 whereequalto('name', 'acacia publishings'); 36 37 final parseresponse publisherresponse = await publisherquerya query(); 38 if (!publisherresponse success) { 39 return; 40 } 41 final publishera = publisherresponse results? first as parseobject; 42 43 // query books with publishera 44 final querybuilder\<parseobject> bookquery = 45 querybuilder\<parseobject>(parseobject('book')) 46 whereequalto('publisher', publishera); 47 48 final parseresponse bookresponse = await bookquery query(); 49 50 if (!bookresponse success) { 51 setstate(() { 52 results clear(); 53 }); 54 } else { 55 setstate(() { 56 results = bookresponse results as list\<parseobject>; 57 }); 58 } 59 } 60 61 void doquerymatches() async { 62 // create inner book query 63 final querybuilder\<parseobject> bookquery = 64 querybuilder\<parseobject>(parseobject('book')) 65 wheregreaterthan('publishingdate', datetime(2010, 01, 01)); 66 67 // query bookstore using inner book query 68 final querybuilder\<parseobject> bookstorequery = 69 querybuilder\<parseobject>(parseobject('bookstore')) 70 wherematchesquery('books', bookquery); 71 72 final parseresponse bookstoreresponse = await bookstorequery query(); 73 if (!bookstoreresponse success) { 74 setstate(() { 75 results clear(); 76 }); 77 } else { 78 setstate(() { 79 results = bookstoreresponse results as list\<parseobject>; 80 }); 81 } 82 } 83 84 void doqueryrelatedto() async { 85 // get book object 86 final querybuilder\<parseobject> bookquery = 87 querybuilder\<parseobject>(parseobject('book')) 88 whereequalto('title', 'can you believe it?'); 89 90 final parseresponse bookresponse = await bookquery query(); 91 if (!bookresponse success) { 92 return; 93 } 94 95 final book = bookresponse results? first as parseobject; 96 97 // get author with relation with book can you believe it? 98 final querybuilder\<parseobject> authorsquery = 99 querybuilder\<parseobject>(parseobject('author')) 100 whererelatedto('authors', 'book', book objectid!); 101 102 final parseresponse authorresponse = await authorsquery query(); 103 104 if (!authorresponse success) { 105 setstate(() { 106 results clear(); 107 }); 108 } else { 109 setstate(() { 110 results = authorresponse results as list\<parseobject>; 111 }); 112 } 113 } 114 115 void doclearresults() async { 116 setstate(() { 117 results clear(); 118 }); 119 } 120 121 @override 122 widget build(buildcontext context) { 123 return scaffold( 124 body padding( 125 padding const edgeinsets all(16 0), 126 child column( 127 crossaxisalignment crossaxisalignment stretch, 128 children \[ 129 container( 130 height 200, 131 child image network( 132 'https //blog back4app com/wp content/uploads/2017/11/logo b4a 1 768x175 1 png'), 133 ), 134 center( 135 child const text('flutter on back4app geopoint', 136 style textstyle(fontsize 18, fontweight fontweight bold)), 137 ), 138 sizedbox( 139 height 8, 140 ), 141 container( 142 height 50, 143 child elevatedbutton( 144 onpressed doquerypointer, 145 child text('query a'), 146 style elevatedbutton stylefrom(primary colors blue)), 147 ), 148 sizedbox( 149 height 8, 150 ), 151 container( 152 height 50, 153 child elevatedbutton( 154 onpressed doquerymatches, 155 child text('query b'), 156 style elevatedbutton stylefrom(primary colors blue)), 157 ), 158 sizedbox( 159 height 8, 160 ), 161 container( 162 height 50, 163 child elevatedbutton( 164 onpressed doqueryrelatedto, 165 child text('query c'), 166 style elevatedbutton stylefrom(primary colors blue)), 167 ), 168 sizedbox( 169 height 8, 170 ), 171 container( 172 height 50, 173 child elevatedbutton( 174 onpressed doclearresults, 175 child text('clear results'), 176 style elevatedbutton stylefrom(primary colors blue)), 177 ), 178 sizedbox( 179 height 8, 180 ), 181 text( 182 'result list ${results length}', 183 ), 184 expanded( 185 child listview\ builder( 186 itemcount results length, 187 itembuilder (context, index) { 188 final o = results\[index]; 189 return container( 190 padding const edgeinsets all(4), 191 decoration 192 boxdecoration(border border all(color colors black)), 193 child text('${o tostring()}'), 194 ); 195 }), 196 ) 197 ], 198 ), 199 )); 200 } 201 } find your application id and client key credentials navigating to your app dashboard at back4app website https //www back4app com/ update your code in main dart with the values of your project’s applicationid and clientkey in back4app keyapplicationid = app id keyclientkey = client key run the project, and the app will load as shown in the image conclusion at the end of this guide, you learned how relational queries work on parse and how to perform them on back4app from a flutter app in the next guide, you will learn how to work with users in parse