In this guide, you will perform relational queries in Parse and implement a React component using these queries. You will learn how to set up and query realistic data using Back4App and React.
If you want to run this guide’s example project, you should set up the Ant Design library.
Goal
Query relational data stored on Back4App from a React App.
1 - Understanding the Parse.Query class
Any Parse query operation uses the Parse.Query object type, which will help you retrieve specific data from your database throughout your app. It is crucial to know that a Parse.Query will only resolve after calling a retrieve method (like Parse.Query.find or Parse.Query.first), so a query can be set up and several modifiers can be chained before actually being called.
To create a new Parse.Query, you need to pass as a parameter the desired Parse.Object subclass, which is the one that will contain your query results. An example query can be seen below, in which a fictional Book subclass is being queried.
JS
1// This will create your query2let parseQuery =newParse.Query("Book");3// The query will resolve only after calling this method4let queryResult =await parseQuery.find();
Let’s create an assortment of classes, which will be the target of our queries in this guide. The classes are: Author, Book, Publisher and BookStore, in which Book has a 1:N relation with Publisher and N:N with Author, and BookStore has an N:N relation with Book.
On Parse JS Console it is possible to run JavaScript code directly, querying and updating your application database contents using the JS SDK commands. Run the code below from your JS Console and insert the data on Back4App. Here is how the JS console looks like in your dashboard:
Go ahead and create the classes with the following example content:
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”) using the basic Parse.Query.equalTo method:
JS
1// Get PublisherA object2const PublisherAQuery =newParse.Query('Publisher');3 PublisherAQuery.equalTo('name','Acacia Publishings');4const PublisherA =await PublisherAQuery.first();56// Query Books with PublisherA7const bookQuery =newParse.Query('Book');8 bookQuery.equalTo('publisher', PublisherA);9let queryResults =await bookQuery.find();1011// Let's show the results12for(let result of queryResults){13// You access `Parse.Objects` attributes by using `.get`14 console.log(result.get('title'));15};
Let’s now query which BookStore objects contain Book objects with publishing date greater than 01/01/2010, using an inner query with the Parse.Query.greaterThan method and then the Parse.Query.matchesQuery method:
JS
1// Create inner Book query2const bookQuery =newParse.Query('Book');3 bookQuery.greaterThan('publishingDate',newDate('01/01/2010'));45// Query BookStore using inner Book query6const bookStoreQuery =newParse.Query('BookStore');7 bookStoreQuery.matchesQuery('books', bookQuery);8let queryResults =await bookStoreQuery.find();910// Let's show the results11for(let result of queryResults){12// You access `Parse.Objects` attributes by using `.get`13 console.log(result.get('name'));14};
Let’s now create a more complex relational query, looking for BookStore objects that have at least one Book written by Author “Aaron Writer” (or “AuthorA”), using equalTo and matchesQuery:
JS
1// Get AuthorA object2const AuthorAQuery =newParse.Query('Author');3 AuthorAQuery.equalTo('name','Aaron Writer');4const AuthorA =await AuthorAQuery.first();56// Create inner Book query7const bookQuery =newParse.Query('Book');8 bookQuery.equalTo('authors', AuthorA);910// Query BookStore using inner Book query11const bookStoreQuery =newParse.Query('BookStore');12 bookStoreQuery.matchesQuery('books', bookQuery);13let queryResults =await bookStoreQuery.find();1415// Let's show the results16for(let result of queryResults){17// You access `Parse.Objects` attributes by using `.get`18 console.log(result.get('name'));19};
4 - Query from a React component
Let’s now use our example queries inside a component in React, with a simple interface having a list showing results and also buttons for calling the queries. This is how the component code is laid out, note the doQuery functions, containing the example code from before.
JavaScript
TypeScript
1import React,{ useState,FC, ReactElement }from'react';2import'./App.css';3import{ Button, Divider }from'antd';4import{ CloseOutlined, SearchOutlined }from'@ant-design/icons';5const Parse =require('parse/dist/parse.min.js');67exportconst QueryRelational:FC<{}>=(): ReactElement =>{8// State variable9const[queryResults, setQueryResults]=useState<Parse.Object[]>();1011constdoQueryA=asyncfunction():Promise<boolean>{12// Get PublisherA object13const PublisherAQuery: Parse.Query =newParse.Query('Publisher');14 PublisherAQuery.equalTo('name','Acacia Publishings');15const PublisherA: Parse.Object |undefined=await PublisherAQuery.first();1617// Query Books with PublisherA18const bookQuery: Parse.Query =newParse.Query('Book');19 bookQuery.equalTo('publisher', PublisherA);2021try{22let results: Parse.Object[]=await bookQuery.find();23setQueryResults(results);24returntrue;25}catch(error){26// Error can be caused by lack of Internet connection27alert(`Error! ${error.message}`);28returnfalse;29}30};3132constdoQueryB=asyncfunction():Promise<boolean>{33// Create inner Book query34const bookQuery: Parse.Query =newParse.Query('Book');35 bookQuery.greaterThan('publishingDate',newDate('01/01/2010'));3637// Query BookStore using inner Book query38const bookStoreQuery: Parse.Query =newParse.Query('BookStore');39 bookStoreQuery.matchesQuery('books', bookQuery);4041try{42let results: Parse.Object[]=await bookStoreQuery.find();43setQueryResults(results);44returntrue;45}catch(error){46// Error can be caused by lack of Internet connection47alert(`Error! ${error.message}`);48returnfalse;49}50};5152constdoQueryC=asyncfunction():Promise<boolean>{53// Get AuthorA object54const AuthorAQuery: Parse.Query =newParse.Query('Author');55 AuthorAQuery.equalTo('name','Aaron Writer');56const AuthorA: Parse.Object |undefined=await AuthorAQuery.first();5758// Create inner Book query59const bookQuery: Parse.Query =newParse.Query('Book');60 bookQuery.equalTo('authors', AuthorA);6162// Query BookStore using inner Book query63const bookStoreQuery: Parse.Query =newParse.Query('BookStore');64 bookStoreQuery.matchesQuery('books', bookQuery);6566try{67let results: Parse.Object[]=await bookStoreQuery.find();68setQueryResults(results);69returntrue;70}catch(error){71// Error can be caused by lack of Internet connection72alert(`Error! ${error.message}`);73returnfalse;74}75};7677constclearQueryResults=asyncfunction():Promise<boolean>{78setQueryResults(undefined);79returntrue;80};8182return(83<div>84<div className="header">85<img
86 className="header_logo"87 alt="Back4App Logo"88 src={89'https://blog.back4app.com/wp-content/uploads/2019/05/back4app-white-logo-500px.png'90}91/>92<p className="header_text_bold">{'React on Back4App'}</p>93<p className="header_text">{'Relational Queries'}</p>94</div>95<div className="container">96<div className="flex_between">97<h2 className="heading">{'Query List'}</h2>98<div className="flex">99<Button
100 onClick={()=>doQueryA()}101 type="primary"102 className="heading_button"103 color={'#208AEC'}104 icon={<SearchOutlined />}105>106QUERYA107</Button>108<Button
109 onClick={()=>doQueryB()}110 type="primary"111 className="heading_button"112 color={'#208AEC'}113 icon={<SearchOutlined />}114>115QUERYB116</Button>117<Button
118 onClick={()=>doQueryC()}119 type="primary"120 className="heading_button"121 color={'#208AEC'}122 icon={<SearchOutlined />}123>124QUERYC125</Button>126<Button
127 onClick={()=>clearQueryResults()}128 type="primary"129 className="heading_button"130 color={'#208AEC'}131 icon={<CloseOutlined />}132>133CLEARRESULTS134</Button>135</div>136</div>137<Divider />138<div className="flex_between">139<div className="flex_child">140{/* Query list */}141{queryResults !==undefined&&142 queryResults.map((result: Parse.Object, index:number)=>(143<div className="list_item" key={`${index}`}>144<p className="list_item_title">{`${result.get('name')!==undefined? result.get('name'): result.get('title')}`}</p>145</div>146))}147{queryResults !==undefined&&148 queryResults.length <=0?(149<p>{'No results here!'}</p>150):null}151</div>152</div>153</div>154</div>155);156};
Also add these classes to your App.css file to fully render the component layout:
This is how the component should look like after rendering and querying by one of the query functions:
Conclusion
At the end of this guide, you learned how relational queries work on Parse and how to perform them on Back4App from a React App. In the next guide, you will learn how to work with Users in Parse.