Shaun Xu

The Sheep-Pen of the Shaun



Shaun, the author of this blog is a semi-geek, clumsy developer, passionate speaker and incapable architect with about 10 years’ experience in .NET and JavaScript. He hopes to prove that software development is art rather than manufacturing. He's into cloud computing platform and technologies (Windows Azure, Amazon and Aliyun) and right now, Shaun is being attracted by JavaScript (Angular.js and Node.js) and he likes it.

Shaun is working at Worktile Inc. as the chief architect for overall design and develop worktile, a web-based collaboration and task management tool, and lesschat, a real-time communication aggregation tool.


My Stats

  • Posts - 119
  • Comments - 501
  • Trackbacks - 0

Tag Cloud

Recent Comments

Recent Posts


Post Categories


Recently I was working on a project to make our production, Worktile Pro, to be able to on-premise deploy. Besides some code changes one of the problem we were facing is how to protect our source code. This can be resolved by compiling to binary. There are some tools can... [Read More]

Our production Worktile Pro was built based on Node.js 0.12 when we firstly developed and at that moment we tried our best to prevent our code from the callback hell.

With Node.js v6 we can use iterator and tj’s co to flatten our code. While with Babel.js we can use Async/Await introduced in ES7.

When I’m developing Worktile Pro with ES6 and ES7, arrow function is one of features I like most. This makes me to use arrow function as anywhere as I could. But I also encountered some problem by using it. For example, in one my previous post, I found arguments are not defined in arrow function. Several days ago I found another problem about this in arrow function.

ES6 introduced a new way to organize modules. It’s different from CommonJS and AMD we are currently using, which through the new keywords import and export. It still NOT being supported by the latest version of Node.js. But fortunately we can leverage Babel.js to play it right now.

When we are rewriting the next version of Instant Message module of our production - Worktile Pro, we used this feature under Node.js v6 and Babel.js. So in this post I would like to introduce what it is and how I was using.

DocumentDB, provided by Microsoft Azure, is a low latency, NoSQL document database service for web high-scale gaming, social, and Internet of Things (IoT) app scenarios. Similar as Microsoft Azure Table Storage Service, when using DocumentDB developers don’t have to worry about managing schemas anymore. But additionally, DocumentDB automatically indexes all JSON documents added to the database, letting you use familiar SQL syntax to query them without having to specify the schema or secondary indices up front.


At the end of March, Microsoft just announced DocumentDB supports MongoDB protocol in preview. This means we can use existing drivers and tools for MongoDB, leveraging existing MongoDB skills for building application against DocumentDB.


Create DocumentDB with MongoDB Protocol

To enable this preview feature, following this blog post to send request. Several days later there will be an email said it's approved.

After that we can create a DocumentDB service with MongoDB Protocol. Login to azure portal and clicked "New" from the left top side, go to "Data + Storage" and search "DocumentDB" we will find "DocumentDB - Protocol Support for MongoDB".


Select this service and click "Create".


Next, specify the name and resource group of this service.


After clicked "Create" it will be creating. This action may take several minutes.



Access DocumentDB through Existing MongoDB Tool

When DocumentDB was firstly released there's no management tool. This is the reason I created a web-based DocumentDB management tool called "My DocumentDB" here and here. But now this DocumentDB service supports MongoDB protocol, we can use client tools for MongoDB to manage DocumentDB. For example, 3T MongoChef, which are are using right now for MongoDB.

First we need to open the DocumentDB service in azure portal, click "All Settings" and select "Connection String", copy the full connection string.


Next, open MongoChef and click "Connection" on the toolbar, then click "New Connection". In the popup window click "From URI" and paste the connection string we have just copied from the portal.


We can click "Test Connection" to verify if it works.


Now we can view and manage our DocumentDB through 3T MongoChef. For example, I created a database with several collections via azure portal.


In 3T MongoChef, click "Refresh All" in left side context menu it load them.


Double click on one of the collection will list all documents, for example "teams" collection. We can also create a document in 3T MongoChef.


And it will be saved on DocumentDB.



Develop with DocumentDB via Existing MongoDB Driver

There are many MongoDB drivers for many program languages. Currently we are using Mongoose in out Node.js backend service and it's easy as well to use Mongoose to connect our DocumentDB.

First, copy the DocumentDB connection string from portal. Then create a Node.js application with NPM packages installed listed below.

  "name": "shx-docdb-mongo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "co": "^4.6.0",
    "lodash": "^4.10.0",
    "mongoose": "^4.4.12"

Includes them and refine a collection's schema as below.

const co = require('co');
const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const TeamSchema = new Schema({
    name: {type: String},
    domain: {type: String},
    members_count: {type: Number, default: 0}
const TeamModel = mongoose.model('team', TeamSchema);

Then set the connection string to a variant for future use. Note that the connection string we copied from azure portal does NOT contain database name, which means it will connect to the authentication database "admin". So we need to insert the database in connection string, normally before "?ssl=true" part.

For example the original connection string was


We need to change to



Below is the database connect function which I wrapped from Mongoose API and returns Promise, as I'm running this sample in Node.js ES6 Mode.

const connect = (url) => {
    return new Promise((resolve, reject) => {
        mongoose.connect(url, null, (error) => {
            if (error) {
                return reject(error);
            else {
                return resolve();


Below is the code to connect and disconnect DocumentDB through Mongoose, which is the native MongoDB Node.js driver underlying.

co(function *() {
    yield mongoose.connect(connectionString);
    console.log('DocuemtDB connected through MongoDB protocol');

    yield mongoose.disconnect();
    console.log('DocuemtDB closed');
}).then(() => {
    console.log('All done.');
}).catch((error) => {
    console.log(`ERROR: ` + JSON.stringify(error, null, 2));



CRUD operations are all supported as well. For example, below code will create 3 documents. Note that "_id" was assigned by default.

let teams = [];
let team1 = new TeamModel({
    name: 'shx',
    domain: 'shx',
    members_count: 10

let team2 = new TeamModel({
    name: 'Worktile',
    domain: 'worktile',
    members_count: 5

let team3 = new TeamModel({
    name: 'Microsoft Azure',
    domain: 'azure'
console.log(JSON.stringify(teams, null, 2));


The code below updated document and then query all documents. Note that "__v" was NOT updated automatically.

yield TeamModel.update({
    name: 'shx'
}, {
    name: 'Shaun Xu'
let teams = yield TeamModel.find({}).exec();
console.log(JSON.stringify(teams, null, 2));


We used "find" method to retrieve all documents. It also support "findOneAndUpdate" as well. Besides, some basic aggregate method are supported, too. Such as "count".

let shx = yield TeamModel.findOneAndUpdate({
    domain: 'shx'
}, {
    name: 'Shaun Ziyan Xu'
}, {
    new: true,
    upsert: false
console.log(JSON.stringify(shx, null, 2));

let result = yield TeamModel.count({}).exec();
console.log(JSON.stringify(result, null, 2));


But when I tried map-reduce, it raised an error back to me. Seems that currently DocumentDB does NOT support MongoDB Map-Reduce command. I had sent an email to DocumentDB team and is waiting for their response.

let result = yield TeamModel.mapReduce({
    map: function () {
        emit(, this.members_count);
    reduce: function (key, values) {
        return values;
console.log(JSON.stringify(result, null, 2));




Why I'm interested in this feature? Well, currently we are using MongoDB which is hosted in several virtual machines and managed by ourselves. But last month we found some database performance issues. As a startup company we don't have enough budget to build a MongoDB expert team. So we have to investigate and tried by ourselves.

After this issue was resolved we found it's necessary to use a self-managed, easy-to-scale NoSQL database service rather than self-host. MongoLab is one of candidate, DocumentDB is the other.

DocumentDB with MongoDB Protocol helps us to migrate our application with very few lines of code changes. Hence if have the same request as our team, you'd better try it as well.


Hope this helps,


All documents and related graphics, codes are provided "AS IS" without warranty of any kind.
Copyright © Shaun Xu. This work is licensed under the Creative Commons License.