Build Full stack application using Flutter ft. Dart frog and MongoDB. Part 2
Tags: flutter, mongodb, tutorial, dart
Published: 2022-12-31 16:09:17

Hello everyone, In the last tutorial we created APIs using **Dart-Frog** for our Flutter Full stack **Pizza Shop** application.

Now we will learn, how to connect **MongoDB** in the dart frog server.

## Prerequisites

- [MongoDB] (https://www.mongodb.com/try/download/community)(CRUD Knowledge)

- and the Dart Basics.

> Note: In case you missed [Part 1](https://dev.to/djsmk123/build-full-stack-application-using-flutter-ft-dart-frog-and-mongodb-part-1-1e2k).


## Let's Start from where we left it.

- Clone following GitHub repository

```
git clone git@github.com:Djsmk123/pizza_shop_dart_backend_part_1.git
```

- Create a new database named **pizza_shop** with Collections named **pizzas** and **orders** as shown below.


![Database and collections creation](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dbz0iyaqi7k0sdb1d4gk.png)

- Now Add the following JSON data to the collection **pizzas**.

```
[
    {
        "id": "50",
        "name": "Baby Bell Peppers",
        "description": "BELL PEPPERS, WATER, SEA SALT, SUNFLOWER OIL",
        "image": "https://assets.zumepizza.com/public/7650vx0h.png",
        "price": 10
      },
      {
        "id": "6",
        "name": "Basil",
        "description": "BASIL LEAVES, WATER, SEA SALT, SUNFLOWER OIL",
        "image": "https://assets.zumepizza.com/public/nfjqscxz.jpg",
        "price": 11
      },
      {
        "id": "110",
        "name": "Daiya Vegan Mozzarella",
        "description":
            "FILTERED WATER, TAPIOCA FLOUR, EXPELLER PRESSED NON-GMO CANOLA AND/OR SAFFLOWER OIL, COCONUT OIL, PEA PROTEIN, SALT, VEGAN NATURAL FLAVOURS, INACTIVE YEAST, VEGETABLE GLYCERIN, XANTHAN GUM, CITRIC ACID, TITANIUM DIOXIDE",
        "price": 12,
        "image": "https://assets.zumepizza.com/public/oo9dpuia.png"
      },
      {
        "id": "74",
        "name": "Kalamata Olives",
        "description": "KALAMATA OLIVES, WATER, SEA SALT, SUNFLOWER OIL",
        "image": "https://assets.zumepizza.com/public/ezuum3ch.png",
        "price": 5
      },
      {
        "id": "75",
        "name": "Mushrooms",
        "description": "MUSHROOMS, WATER, SEA SALT, SUNFLOWER OIL",
        "image": "https://assets.zumepizza.com/public/nfjqscxz.jpg",
        "price": 6
      },
      {
        "id": "76",
        "name": "Onions",
        "description": "ONIONS, WATER, SEA SALT, SUNFLOWER OIL",
        "image": "https://assets.zumepizza.com/public/7650vx0h.png",
        "price": 7
      },
      {
        "id": "77",
        "name": "Pepperoni",
        "description": "PEPPERONI, WATER, SEA SALT, SUNFLOWER OIL",
        "image": "https://assets.zumepizza.com/public/nfjqscxz.jpg",
        "price": 8
      },
      {
        "id": "78",
        "name": "Red Onions",
        "description": "RED ONIONS, WATER, SEA SALT, SUNFLOWER OIL",
        "image": "https://assets.zumepizza.com/public/nfjqscxz.jpg",
        "price": 9
      },
      {
        "id": "79",
        "name": "Roasted Red Peppers",
        "description": "ROASTED RED PEPPERS, WATER, SEA SALT, SUNFLOWER OIL",
        "image": "https://assets.zumepizza.com/public/nfjqscxz.jpg",
        "price": 10
      },
      {
        "id": "80",
        "name": "Spinach",
        "description": "SPINACH, WATER, SEA SALT, SUNFLOWER OIL",
        "image": "https://assets.zumepizza.com/public/nfjqscxz.jpg",
        "price": 11
      },
      {
        "id": "81",
        "name": "Sun Dried Tomatoes",
        "description": "SUN DRIED TOMATOES, WATER, SEA SALT, SUNFLOWER OIL",
        "image": "https://assets.zumepizza.com/public/nfjqscxz.jpg",
        "price": 12
      }
]

```


![pizzas.json](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w2uqx2d0gqulr2vwgovm.png)


- Do same with **orders** with following data
```
[
   {
    "id": 1,
    "user_id": "1",
    "pizza_id": "6",
    "address": "1234 Main St",
    "phone_number": "1234567890",
    "status": "pending"
  }
]
```

- let's Add MongoDB Dependency to our project.

```
   mongo_dart: ^0.8.2
```
Add in the **pubspec.yaml**.

- Create a new folder in the project called **services** which will handle MongoDB services and create a new file called **database_services.dart**.

```

// ignore_for_file: prefer_single_quotes, lines_longer_than_80_chars

import 'package:dart_frog/dart_frog.dart';
import 'package:mongo_dart/mongo_dart.dart';

class DatabaseService {
  static final db = Db("mongodb://localhost:27017/pizza_shop");
  //start the database
  static Future<void> startDb() async {
    if (db.isConnected == false) {
      await db.open();
    }
  }

  //close the database
  static Future<void> closeDb() async {
    if (db.isConnected == true) {
      await db.close();
    }
  }

  //collections
  static final pizzasCollections = db.collection('pizzas');
  static final ordersCollections = db.collection('orders');

  // we will use this method to start the database connection and use it in our routes
  static Future<Response> startConnection(
    RequestContext context,
    Future<Response> callBack,
  ) async {
    try {
      await startDb();
      return await callBack;
    } catch (e) {
      return Response.json(
        statusCode: 500,
        body: {'message': 'Internal server error'},
      );
    }
  }
}
```

- we are going to use the following query for database management

1. [`find()`](https://www.mongodb.com/docs/manual/reference/method/db.collection.find/): To find all the data from given collection.

2. [`findOne(where.eq('key-value',value)`)](https://www.mongodb.com/docs/manual/reference/method/db.collection.findOne/): will use to find specific data from a given collection with the specified value.

3. [`insertOne(data)`](https://www.mongodb.com/docs/drivers/go/current/fundamentals/crud/write-operations/insert/): will use it to insert data in a given collection.

## Let's Edit existing Endpoints

- `/pizzas`: we are going to fetch all pizzas from "PizzaCollection" and will map to the list of `PizzaModel` and then return the same.

`//File name : routes/pizzas.dart`

```

// ignore_for_file: lines_longer_than_80_chars

import 'package:dart_frog/dart_frog.dart';
import 'package:mongo_dart/mongo_dart.dart';

import '../models/pizza_models.dart';
import '../services/database_services.dart';

Future<Response> onRequest(RequestContext context) async {
  return DatabaseService.startConnection(context, getPizzas(context));
}

Future<Response> getPizzas(RequestContext context) async {
  //check if the request is a GET request
  if (context.request.method == HttpMethod.get) {
    //check if query parameter is present
    final params = context.request.uri.queryParameters;
    if (params.containsKey('id')) {
      //return the pizza with the id
      final id = params['id'];
      final doc =
          await DatabaseService.pizzasCollections.findOne(where.eq('id', id));
      if (doc != null && doc.isNotEmpty) {
        final pizza = PizzaModel.fromJson(doc);
        return Response.json(body: {'data': pizza});
      } else {
        return Response.json(
          statusCode: 404,
          body: {'message': 'Pizza not found'},
        );
      }
    } else {
      final docs = await DatabaseService.pizzasCollections.find().toList();
      final pizzas = docs.map(PizzaModel.fromJson).toList();
      return Response.json(body: {'data': pizzas});
    }
  }

  return Response.json(
    statusCode: 404,
    body: {'message': 'Method not allowed'},
  );
}

```

- `/fetchorders`: we will fetch only those docs where `user_id` will be equal to `user_id` in query parameter and then return if exist.

`//File name fetchorders.dart` 

```
// ignore_for_file: lines_longer_than_80_chars

import 'package:dart_frog/dart_frog.dart';
import 'package:mongo_dart/mongo_dart.dart';

import '../models/order_models.dart';
import '../services/database_services.dart';

Future<Response> onRequest(RequestContext context) async {
  return DatabaseService.startConnection(context, getOrders(context));
}

Future<Response> getOrders(RequestContext context) async {
  //check if the request is a GET request
  if (context.request.method == HttpMethod.get) {
    //check if user_id is present
    final params = context.request.uri.queryParameters;
    if (params.containsKey('user_id')) {
      final userId = params['user_id'];
      final doc = await DatabaseService.ordersCollections
          .find(where.eq('user_id', userId))
          .toList();
      final userOrders = doc.map(OrderModel.fromJson).toList();
      if (userOrders.isNotEmpty) {
        return Response.json(body: {'data': userOrders.toList()});
      }
    }
    return Response.json(body: {'message': 'User id not found'});
  }
  return Response.json(
    statusCode: 404,
    body: {'message': 'Method not allowed'},
  );
}

```

- `/createorder`: As we know that this request is **post** so we will check if the `pizza_id` is Valid or not? and then will insert an entry into `orders` collection.

`//File name createorders.dart`

```
// ignore_for_file: avoid_dynamic_calls, noop_primitive_operations

import 'package:dart_frog/dart_frog.dart';
import 'package:mongo_dart/mongo_dart.dart';

import '../models/order_models.dart';
import '../services/database_services.dart';

Future<Response> onRequest(RequestContext context) async {
  return DatabaseService.startConnection(context, createOrder(context));
}

Future<Response> createOrder(RequestContext context) async {
  //check if the request is a POST request
  if (context.request.method == HttpMethod.post) {
    //check if headers is application/json
    final contentType = context.request.headers['content-type'];
    if (contentType == 'application/json; charset=utf-8') {
      //check if body is present
      final body = await context.request.json();

      if (body != null &&
          body['pizza_id'] != null &&
          body['user_id'] != null &&
          body['address'] != null &&
          body['phone_number'] != null) {
        //check valid pizza id

        final pizzas = await DatabaseService.pizzasCollections
            .findOne(where.eq('id', body['pizza_id']));
        final isValidPizzaId = pizzas != null && pizzas.isNotEmpty;
        if (isValidPizzaId) {
          final orders = OrderModel.fromJson({
            'id': DateTime.now().millisecondsSinceEpoch.toInt(),
            'pizza_id': body['pizza_id'],
            'user_id': body['user_id'],
            'status': 'pending',
            'address': body['address'],
            'phone_number': body['phone_number'],
          });
          await DatabaseService.ordersCollections.insert(orders.toJson());
          return Response.json(
            statusCode: 201,
            body: {
              'message':
                  'Order created successfully with order id: ${orders.id}'
            },
          );
        } else {
          return Response.json(
            statusCode: 404,
            body: {'message': 'Invalid spizza id'},
          );
        }
      } else {
        return Response.json(
          statusCode: 404,
          body: {'message': 'All fields are required'},
        );
      }
    }

    return Response.json(
      statusCode: 404,
      body: {'message': 'Content-Type must be application/json'},
    );
  }
  return Response.json(
    statusCode: 404,
    body: {'message': 'Method not allowed'},
  );
}

```

- Now you can delete the `constants. dart` file.

## Output

{% vimeo https://vimeo.com/785420464 %}


> Note: we are not going to build the front end on the web so you can use my repository for the front end.


[Pizza_shop_web_application](https://github.com/Djsmk123/pizza_shop_flutter_web_app)



## Happy New year to Everyone 

![meme1](https://external-preview.redd.it/0n6iBJzBY-gLgb6Yn8rEF7gKGqNOLM2JrtZTd2BoWqg.png?auto=webp&s=f68de69a27bb3a0831695b86574f4ab129b65c9f)

> We are done .....................

Stay Tuned .....

- [**Source code part 1**](https://github.com/Djsmk123/pizza_shop_dart_backend_part_1)

- [**Source code part 2**](https://github.com/Djsmk123/pizza_shop_dart_frog_backend)

- [**Source code Flutter web**](https://github.com/Djsmk123/pizza_shop_flutter_web_app)

> Follow me:

- [GitHub](https://github.com//djsmk123)

- [LinkedIn](https://www.linkedin.com/in/md-mobin-bb928820b)

- [Twitter](https://twitter.com/smk_winner)