Using the mongo_dart driver to store the todo data in MongoDB

MongoDB drivers exist for a whole range of programming languages, including Dart. We will use mongo_dart in our app, which is a server-side driver implemented purely in Dart. Simply add mongo_dart: any to your app's pubspec.yaml, and issue pub install. In the code, write:

import 'package:mongo_dart/mongo_dart.dart';

todo_mongodb is a version of todo_server_dartling_mysql, but now use MongoDB as a persistent data source (clone the project from https://github.com/dzenanr/todo_mongodb). It contains a client app todo_client_idb, identical to the one in the previous section, which stores data in IndexedDB. The server part todo_server_dartling_mongodb can be started by running bin/server.dart; you should see in the editor or the console:

Server at http://127.0.0.1:8080;

If you see the following exception, it means that the mongod server has not yet been started:

SocketException: Connection failed (OS Error: No connection could be made because the target machine actively refused it., errno = 10061), address = 127.0.0.1, port = 27017.

Run a Dartium client (todo_client_idb/web/app.html) from the editor and a JavaScript client in Chrome or another browser. Fill in some tasks if you see nothing to do and click the To Server button. The mongod console outputs that it has created a data file with index, and that it has inserted a number of rows:

Fri Aug 23 11:19:55.839 [FileAllocator] allocating new datafile datadb	odo.1,
filling with zeroes...
Fri Aug 23 11:19:55.842 [conn1] build index todo.tasks { _id: 1 }
Fri Aug 23 11:19:55.844 [conn1] build index done.  scanned 0 total records. 0.002
 secs
Fri Aug 23 11:19:55.846 [conn1] insert todo.tasks ninserted:1 keyUpdates:0 locks(
micros) w:412870 412ms
Fri Aug 23 11:19:56.466 [FileAllocator] done allocating datafile datadb	odo.1,
 size: 128MB,  took 0.625 secs

Synchronize the other clients by clicking their From Server button. To verify that the data is actually in MongoDB, open a Mongo shell by typing mongo in a console and issuing the commands to retrieve the documents from the tasks collection in the todo database:

> use todo

The output will be as follows:

switched to db todo

The command to retrieve the documents is as follows:

> db.tasks.find()

The output will be as follows:

{ "_id" : ObjectId("5217293b479e4132cdecef0e"), "title" : "administration", "comp
leted" : false, "updated" : ISODate("2013-08-16T09:14:50.569Z") }   ...

Running test/mongodb_test.dart is an alternative to create and populate the database todo with a tasks collection. From the structure of our app, we can deduce that the data access code resides in lib/persistence/mongodb.dart, which contains the classes TodoDb and TaskCollection. Let us now see how our Dart code reaches out to MongoDB. In the main method of the server script, we see:

void main() {
  db = new TodoDb();                                             (1)
  db.open().then((_) {                                           (2)
    start();
  });
}

Line (1) calls the constructor from TodoDb, and in line (2), the database is opened. The following is the code from the TodoDb class:

class TodoDb implements ActionReactionApi {
  static const String DEFAULT_URI = 'mongodb://127.0.0.1/';
  static const String DB_NAME = 'todo';

  TodoModels domain;
  DomainSession session;
  MvcEntries model;
  Tasks tasks;

  Db db;

  TaskCollection taskCollection;

  TodoDb() {                                                   (3)
    var repo = new TodoRepo();
    domain = repo.getDomainModels('Todo'),
    domain.startActionReaction(this);
    session = domain.newSession();
    model = domain.getModelEntries('Mvc'),
    tasks = model.tasks;
  }

  Future open() {
    Completer completer = new Completer();
    db = new Db('${DEFAULT_URI}${DB_NAME}'),                   (4)
    db.open().then((_) {                                       (5)
      taskCollection = new TaskCollection(this);               (6)
      taskCollection.load().then((_) {                         (7)
        completer.complete();
      });
    }).catchError(print);
    return completer.future;
  }

  close() {
    db.close();
  }

  react(ActionApi action) {
    if (action is AddAction) {
      taskCollection.insert((action as AddAction).entity);
    } else if (action is RemoveAction) {
      taskCollection.delete((action as RemoveAction).entity);
    } else if (action is SetAttributeAction) {
      taskCollection.update((action as 	SetAttributeAction).entity);
    }
  }
}

The constructor starting in line (3) does everything necessary to start up the Dartling model. The open method creates a new MongoDB database in line (4) (with the substituted value):

db = new Db('mongodb://127.0.0.1/todo );

The Db class comes from mongo_dart; it has an open method called in line (5). From the then keyword, we see that it returns a Future as expected. As dictated by Dartling, any change in the app's data calls react to update the model and the database, as TodoDb listens to actions in the model through the line:

domain.startActionReaction(this)); 

When an action happens, all listeners are informed about that action in the react method for listeners. The TaskCollection class, whose object is constructed in line (6), is the closest we will get to MongoDB in this project, again, using Futures throughout. The code is as follows:

   class TaskCollection {
  static const String COLLECTION_NAME = 'tasks';
  TodoDb todo;
  DbCollection dbTasks;

  TaskCollection(this.todo) {
    dbTasks = todo.db.collection(COLLECTION_NAME);            (8)
  }

  Future load() {                                             (9)
    Completer completer = new Completer();
    dbTasks.find().toList().then((taskList) {
      taskList.forEach((taskMap) {
        var task = new Task.fromDb(todo.tasks.concept, taskMap);
        todo.tasks.add(task);
      });
      completer.complete();
    }).catchError(print);
    return completer.future;
  }

  Future<Task> insert(Task task) {
    var completer = new Completer();
    var taskMap = task.toDb();
    dbTasks.insert(taskMap).then((_) {
      print('inserted task: ${task.title}'),
      completer.complete();
    }).catchError(print);
    return completer.future;
  }

  Future<Task> delete(Task task) {
    var completer = new Completer();
    var taskMap = task.toDb();
    dbTasks.remove(taskMap).then((_) {
      print('removed task: ${task.title}'),
      completer.complete();
    }).catchError(print);
    return completer.future;
  }

  Future<Task> update(Task task) {
    var completer = new Completer();
    var taskMap = task.toDb();
    dbTasks.update({"title": taskMap['title']}, taskMap).then((_){
      print('updated task: ${task.title}'),
      completer.complete();
    }).catchError(print);
    return completer.future;
   }
}

It contains a DbCollection object (also defined in mongo_dart) named dbTasks, which mirrors the tasks collection in the database through the assignment in line (8) of the constructor. In line (9), its load method (called in the previous code snippet in line (7)) calls find() on dbTasks. When the results return, a new Task object is made for each document, found, and added to the tasks collection. The insert, delete, and update methods respectively call insert, remove, and update on the DbCollection object dbTasks. Notice the exceptional handling clause that will signal any error:

.catchError(print);

When a server starts, all data from a database are loaded into the model in the main memory. When the model changes, these changes are propagated immediately to the database through actions/reactions. In this approach, a database system is used only minimally: all searches for the data are done in the main memory without using the slower database system. With Dartling, a model is not dependent on MongoDB—the model does not call the insert, update, and remove methods. The use of (only a few methods of) the mongo_dart driver shields us from using and knowing the slightly more elaborate MongoDB commands in our Dart code. The complete API reference of the driver can be found at http://vadimtsushko.github.io/mongo_dart/mongo_dart/Db.html.

Again, we clearly see the advantages of using a modeling framework and a well-structured library; our data access code in lib/persistence was all we needed to adapt while changing from the MySQL version to the MongoDB version!

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.75.221