Using local MiniMongo database in Tizen

Introduction

In the previous article I've described the Blaze templating engine that is a powerful, efficient and easy tool for creating applications' UIs. It's a reactive templating engine. It means that any change to the underlying data is automatically reflected in the UI. In this article I'm going to describe in more details how to deal with the Model layer (in the MVC pattern) when creating an application using Blaze. I will focus on a local MongoDB database that is shipped with the Blaze library. It's called MiniMongo because it's stripped out of few features. However it's good enough to use it in Tizen applications, even a complex one. Moreover MiniMongo is a reactive data source, which means that you don't have to create complex relations between the Model and the View layers. It just happens almost automatically when using Blaze.

Creating collections

MongoDB is a document oriented database. Records are kept as documents in collections. Any JSON compatible object can be a document and each document can have different attributes. Let's see how to create a collection.

var Collection = Package.minimongo.LocalCollection;
var Items = new Collection();

As you can see, we've created reference to the Package.minimongo.LocalCollection constructor. Now we can use our Collection reference to create new Items collection. That's it.

Adding the documents to a collection

To add a document to collection, we have to use the insert method of the Collection.

Collection.insert(document, [callback]);

The insert function takes one mandatory parameter which is the document to insert and one optional which is a callback that will be executed after insertion is completed.

And here is an example of a document insertion.

Items.insert({
  name: 'Example name',
  order: 5,
  done: false
}, function() {
  alert('Document inserted!');
});

Deleting documents from a collection

To delete document from a collection, we have to use the remove method of the Collection object.

Collection.remove(mongoSelector, [callback]);

It takes a mongo selector as the first argument and an optional callback as the second. Mongo selectors available in MiniMongo are decribed in the documentation.

We can use a simple selector to select and remove documents that have attributes equal to those we've provided.

Items.remove({
  _id: documentId
});

Items.remove({
  name: 'Example name'
});

Items.remove({
  order: 5
});

Or more complex.

Delete all the documents where order is greater than 3.

Items.remove({
  order: {
    $gt: 3
  }
});

All Mongo selectors are described here. You can use the following selectors:

  • $and - Joins query clauses with a logical AND returns all documents that match the conditions of both clauses.
  • $or - Joins query clauses with a logical OR returns all documents that match the conditions of either clause.
  • $nor - Joins query clauses with a logical NOR returns all documents that fail to match both clauses.
  • $not - Inverts the effect of a query expression and returns documents that do not match the query expression.
  • $where - Matches documents that satisfy a JavaScript expression.
  • $in - Matches any of the values that exist in an array specified in the query.
  • $all - Matches arrays that contain all elements specified in the query.
  • $lt - Matches values that are less than the value specified in the query.
  • $lte - Matches values that are less than or equal to the value specified in the query.
  • $gt - Matches values that are greater than the value specified in the query.
  • $gte - Matches values that are greater than or equal to the value specified in the query.
  • $ne - Matches all values that are not equal to the value specified in the query.
  • $nin - Matches values that do not exist in an array specified to the query.
  • $exists - Matches documents that have the specified field.
  • $mod - Performs a modulo operation on the value of a field and selects documents with a specified result.
  • $size - Selects documents if the array field is a specified size.
  • $type - Selects documents if a field is of the specified type.
  • $regex - Selects documents where values match a specified regular expression.
  • $elemMatch - Selects documents if element in the array field matches all the specified $elemMatch condition.

Updating documents in a collection

To update a document in collection, we have to use the update method of the Collection.

Collection.update(mongoSelector, mongoModifier, [options], [callback]);

As in remove method, you have to also pass a mongo selector as the first argument of the update function.

The second argument is a mongo modifier whose description you can find in the official MongoDB documentation. In MiniMongo you can use the following Mongo modifiers:

  • $inc - The $inc operator increments a field by a specified value
  • $set - The $set operator replaces the value of a field to the specified value.
  • $unset - The $unset operator deletes a particular field.
  • $push - The $push operator appends a specified value to an array.
  • $pushAll - The $pushAll operator appends the specified values to an array.
  • $addToSet - The $addToSet operator adds a value to an array only if the value is not already in the array
  • $pop - The $pop operator removes the first or last element of an array.
  • $pull - The $pull operator removes from an existing array all instances of a value or values that match a specified query.
  • $pullAll - The $pullAll operator removes all instances of the specified values from an existing array.
  • $rename - The $rename operator updates the name of a field.
  • $bit - The $bit operator performs a bitwise update of a field.

The third argument of the update method is an optional options object. Possible options are:

  • multi - When set to true it tries to modify all matching documents, otherwise it modifies only first matching document.
  • upsert - When set to true it tries to insert a document if no matching documents are found.

And as the last argument an optional callback function can be passed.

Querying a collection

We have two functions for taking documents from a collection. Those are find and findOne.

Collection.find([selector], [options]);
Collection.findOne([selector], [options]);

The first one returns a cursor to all documents that matches the given selector, where the second one returns only the first document.

The second argument is a options object which can have the following attributes:

  • sort - Sort order (default: natural order).
  • skip - Number of results to skip at the beginning.
  • limit - Maximum number of results to return.
  • fields - Dictionary of fields to return or exclude.
  • reactive - Pass false to disable reactivity.
  • transform - Overrides transform function on the Collection for this cursor.

Here is an example code which is taking all items where the order field is greater than 3. It limits the document count to 5, takes only the order field (and mandatory _id) and sorts it in descending order by the order field.

Items.find({
  order: {
    $gt: 3
  }
}, {
  limit: 5,
  fields: ['order'],
  sort: {
    order: -1
  }
});

Using MiniMongo with Blaze

Now, let's take a look how to use MiniMongo in the Blaze templates. All examples are taken from the sample application attached to this article.


A screenshot taken from the sample application.

The sample application is a simple to do task list. You can create new tasks, modify, remove and mark as done/to do. In the application we have only two templates, one for the main application container and second for a given task.

<script type="text/spacebars" name="main">
  <ul>
    {{#each items}}{{> item}}{{/each}}
  </ul>
</script>

<script type="text/spacebars" name="item">
  <li class="{{#if done}}done{{/if}}"><span class="checkbox"></span>
    <input type="text" value="{{name}}" />
  </li>
</script>

To pass our Items collection to the template we have to write the following code.

Template.main.helpers({
  items: function() {
    return Items.find({}, {
      sort: {
        order: 1
      }
    });
  }
});

As you can see it's pretty simple. We declare an items helper for the main template. Inside the helper we execute the find function from the Items collection to retrieve all the tasks in the ascending order. Now having this simple code, the application's UI will be automatically updated whenever any new task is added, updated or removed from the Items collection.

I've defined some events for the templates to handle operations on tasks.

  • You can add new task by clicking the ENTER/DONE key. When the caret cursor is positioned at the beginning of the task name, a new task will be added before the current task. New task will be added after the current one when the caret cursor is positioned at the end of the task name. When the caret cursor is in the middle of the task name, the task will be split into two separate tasks.
  • You can modify the task name by just clicking on it and typing.
  • You can remove task by removing the task name using the BACKSPACE key.
  • You can mark task as done/to do, by just clicking a checkbox in front of the task name.

I'm not going to describe how each of those operations have been made. You can go to the source code of the application and check it out. It's pretty simple and doesn't need further explanation.

文件附件: