---
title: N:N Relationship
slug: docs/flutter/parse-sdk/data-objects/flutter-many-to-many-relationship
description: In this guide you'll learn how to create and query many-to-many data object associations in Parse on Flutter
image: https://www.back4app.com/images/logo-social.png
docTags: 
createdAt: 2024-03-15T15:45:12.640Z
---

# Many to Many Relationship on Flutter

## Introduction

In the previous guide, we learned how to use one-to-many relations and we will continue with our project. In this guide, we will focus on the most common relation: many-to-many. There are three ways to create a many-to-many relation in Parse.

- The first is using the Parse <font color="#2166ae">`Relations`</font>, which is the fastest in creation and query time. We will use this in this guide.
- The second is using<font color="#2166ae">`Arrays`</font> of <font color="#2166ae">`Pointers`</font> which can lead to slow query times depending on their size.
- The third is using<font color="#2166ae">`JoinTable`</font> where the idea from classical database. When there is a many-to-many relation, we combine every <font color="#2166ae">`objectId`</font> or <font color="#2166ae">`Pointer`</font> from both sides together to build a new separate table in which the relationship is tracked.

In this guide you will implement a <font color="#2166ae">`many-to-many`</font> relationship on a Flutter Book Registration App using the Parse <font color="#2166ae">`Relations`</font>. You will learn how to create and query many-to-many data relations and how to perform queries returning data from related objects, using Back4App and the Flutter SDK.

::embed[]{url="https://www.youtube.com/embed/Vfyo-g8vjPs"}

## Prerequisites

:::hint{type="info"}
- [Android Studio ](https://developer.android.com/studio)or [VS Code installed](https://code.visualstudio.com/) (with [Plugins](https://docs.flutter.dev/get-started/editor) Dart and Flutter)
- **Note: The Flutter app created in previous guide**
- Complete the previous guide so you can have a better understanding of the <font color="#2166ae">`one-to-may relationship`</font> class
- A device (or virtual device) running Android or iOS.
:::

## 1 - Run the Book App Template

If you have not completed the previous guide you can clone and run the complete [Book Flutter App](https://github.com/templates-back4app/flutter_associations) project from our repository. You can also take a look at the [previous guide](https://www.back4app.com/docs/flutter/parse-sdk/data-objects/%7Bsite.baseurl%7D%7D//flutter/parse-sdk/data-objects/flutter-one-to-many-relationship) to better understand the App template. Below you can find a visual representation of Book Registration data model.

![](https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/Swe2-7FvMIocPiAXjY-N-_image.png)

## 2 - Save a Book object and its Author’s

Open the Flutter project from the previous guide [One to many Relationship on Flutter](https://www.back4app.com/docs//flutter/parse-sdk/data-objects/flutter-one-to-many-relationship). Search for the function <font color="#2166ae">`doSaveBook`</font> in file <font color="#2166ae">`main.dart`</font>, and replace with the code below inside the <font color="#2166ae">`Future<void> doSaveBook()`</font> function below. This function will create a new Book in Back4app data store with relations.

```dart
1       final book = ParseObject('Book')
2         ..set('title', controllerTitle.text.trim())
3         ..set('year', int.parse(controllerYear.text.trim()))
4         //the objectId will be converted to a Pointer on the save() method
5         ..set('genre', ParseObject('Genre')..objectId = genre.objectId)
6         //you can also convert to a Pointer object before the saving using the .toPointer() method
7         ..set('publisher',
8             (ParseObject('Publisher')..objectId = publisher.objectId).toPointer())
9         //Saving a List of Authors for the Book
10        ..addRelation(
11            'authors',
12            authors
13                .map((o) => ParseObject('Author')..objectId = o.objectId)
14                .toList());
15 
16      await book.save();
```

To build this function, follow these steps:

- 1\. Create a new instance of the Parse<font color="#2166ae">`Book`</font> class with the command <font color="#2166ae">`ParseObject('Book')`</font>.
- 2\. Use the <font color="#2166ae">`set`</font> function to set the fields for this object.
  - 2.1.<font color="#2166ae">`title`</font>is a text attributes that receive value from the text controller.
  - 2.2.<font color="#2166ae">`genre`</font> receives the value by defining a <font color="#2166ae">`ParseObject`</font> with the <font color="#2166ae">`objectId`</font> of the selected <font color="#2166ae">`Genre`</font>. (*Parse will convert to pointer on save*)
  - 2.3.<font color="#2166ae">`publisher`</font> receives the value by defining a <font color="#2166ae">`ParseObject`</font> with the <font color="#2166ae">`objectId`</font> of the selected <font color="#2166ae">`Publisher`</font>. (*Note that we can specify for Parse that we want to save as a&#x20;*<font color="#2166ae">`pointer`</font>*&#x20;using the&#x20;*<font color="#2166ae">`toPointer()`</font>*&#x20;method*)
  - 2.4.<font color="#2166ae">`authors`</font>. We call the <font color="#2166ae">`addRelation`</font> method of <font color="#2166ae">`ParseObject`</font>, sending a list of <font color="#2166ae">`ParseObject`</font> with the <font color="#2166ae">`objectId`</font> of the selected <font color="#2166ae">`Authors`</font>.
- 3\. Call the<font color="#2166ae">`save`</font> function in <font color="#2166ae">`ParseObject`</font>, which will effectively register the object to your database in the Back4app Dashboard.

Run the App and test the new <font color="#2166ae">`doSaveBook()`</font> function

- First, access the dashboard and delete the books that were previously registered in the previous guide.
- Click on the <font color="#2166ae">`Add Book`</font> button.
- Fill book information with Authors.
- Click on <font color="#2166ae">`Save Book`</font> button

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/O0kajxCDCm8k3Q2aBeI_u_image.png" size="30" width="323" height="627" position="center" showCaption="false"}

To confirm that the new object is save in the database with relations, you can access the <font color="#2166ae">`Back4app Dashboard`</font> and access <font color="#2166ae">`Book`</font> class.

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/lE7tRKvGzi1YioqFBkxZb_image.png" size="30" width="323" height="627" position="center" showCaption="false"}

Clicking on the object pointer/relation value in your dashboard will take you to the referenced object entry. It may seem like a harmless feature, but this makes debugging and error tracing much quicker than searching for it manually.

## 3 - Query the Book Details with Relations

This function will query Book Details in Back4app database, returning relationship data. In some situations, you want to return multiple types of related objects in one query. You can do this with the <font color="#2166ae">`includeObject`</font> method. In our example, we want to return the books, with information from Genre and Publishers.

Search for the function <font color="#2166ae">`getBookDetail`</font> in the file <font color="#2166ae">`main.dart`</font>, then replace the code below inside <font color="#2166ae">`getBookDetail(ParseObject book)`</font> function:

```dart
1       QueryBuilder<ParseObject> queryBook =
2           QueryBuilder<ParseObject>(ParseObject('Book'))
3             ..whereEqualTo('objectId', book.objectId)
4             ..includeObject(['publisher', 'genre']);
5   
6       final ParseResponse responseBook = await queryBook.query();
7
8       if (responseBook.success && responseBook.results != null) {
9         final book = (responseBook.results.first) as ParseObject;
10        bookTitle = book.get<String>('title');
11        bookYear = book.get<int>('year');
12        bookGenre = book.get<ParseObject>('genre').get<String>('name');
13        bookPublisher = book.get<ParseObject>('publisher').get<String>('name');
14        loadedData = true;
15      }
16
17      QueryBuilder<ParseObject> queryAuthors =
18          QueryBuilder<ParseObject>(ParseObject('Author'))
19            ..whereRelatedTo('authors', 'Book', book.objectId);
20
21      final ParseResponse responseAuthors = await queryAuthors.query();
22
23      if (responseAuthors.success && responseAuthors.results != null) {
24        bookAuthors = responseAuthors.results
25            .map((e) => (e as ParseObject).get<String>('name'))
26            .toList();
27      }
```

To build this function, follow these steps:

1. Create an instance of<font color="#2166ae">`ParseQuery`</font> object for <font color="#2166ae">`Book`</font> class. Insert a condition in the query, to search <font color="#2166ae">`Books`</font> where <font color="#2166ae">`objectId`</font> field is equal <font color="#2166ae">`objectId`</font> of the selected book.
2. We use the includeObject method, informing the fields of the pointers that we want to return the data in the same query: Genre and Publisher. You can also do multi level includeObject using dot notation. Exemple : \`..includeObject(\[‘post’, ‘post.authors’]);
3. Do a Query’s search method using <font color="#2166ae">`query()`</font> method.
4. If the operations succeed, object in <font color="#2166ae">`Book`</font> will be returned.
5. We use the get method to retrieve the data. For fields that are pointers, we will first need to retrieve the pointer, then obtain its data. Example:<font color="#2166ae">`bookGenre = book.get<ParseObject>('genre').get<String>('name');`</font>

In the second stage of processing, we need to recover the Authors associated with the Book.

To build this function, follow these steps:

1. Create an instance of<font color="#2166ae">`ParseQuery`</font> object for <font color="#2166ae">`Authors`</font> class. Insert a condition in the query, using <font color="#2166ae">`whereRelatedTo`</font> operator to search <font color="#2166ae">`Authors`</font> relationship with <font color="#2166ae">`Book`</font>, where <font color="#2166ae">`Book`</font> is equal <font color="#2166ae">`objectId`</font> of the selected book.
2. Do a Query’s search method using <font color="#2166ae">`query()`</font> method.
3. If the operations succeed, object in <font color="#2166ae">`Book`</font> will be returned.
4. We use the get method to retrieve the data.

Run the App and test the new Query.

First, click on the <font color="#2166ae">`List Publisher/Book`</font> button.

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/MtZZXEKd2vUJ7afLiv-wR_image.png" size="30" width="323" height="627" position="center" showCaption="false"}

Select a book from the list. The next screen will display the data for the books and their relationships.

::Image[]{src="https://api.archbee.com/api/optimize/yD3zCY-NNBBIfd0uqcfR5/IkAfHVHlwA-8sTmhK7cxh_image.png" size="30" width="328" height="637" position="center" showCaption="false"}

## It’s done!

At this point, you learned how to create and query many-to-many relations and how to perform queries returning data from related objects in Parse on <font color="#2166ae">`Flutter`</font>.
