Azure DocumentDB Demo


December the 1st, 2015, I’m doing a presentation to a Montreal User Group, MS DEV MTL. Here is the script of each demo.  Enjoy!

UPDATE:  You can see the presentation slides here.

 

Account Creation & Adding Documents

For the creation of an Azure DocumentDB account, allow me to refer to myself in Creating an Azure DocumentDB account.

In order to add a database, in your DocumentDB account blade, click “Add Database”, name it Demo-DB.

Select that database ; that will open the database blade. Click “Add Collection”, name it demo. Change the price tier to S1.

Select the collection you just created. That will open the collection blade. We are going to create two documents. For that, click “Create Document” on top of the collection blade. First document:

{
"firstName" : "Vincent-Philippe",
"lastName" : "Lauzon",
"office" : "MTL"
}

Second document:

{
"office" : "MTL",
"address" :
{
"streetNumber" : 2000,
"streetName" : "McGill College",
"streetType" : "Avenue",
"inBuilding" : "Suite 500",
"postalCode" : "H3A 3H3"
}
}

Now, let’s look at those document within the collection. In the collection blade, click “Document Explorer” (at the bottom). You will notice a few things:

  • Both documents were added an id property containing a generated GUID
  • Both documents didn’t have the same schema
  • JavaScript types string and integer were used

Let’s add a third document:

{
"firstName" : "John",
"lastName" : "Smith",
"office" : "Calgary",
"id" : "emp-john-smith",
"phoneNumber" : "123-456-7890"
}

You can go ahead and look at the document and observe that:

  • We manually inserted the id of the document here ; DocumentDB used the id
  • The schema was slightly different that the other employee

Simple Querying

For querying, in the collection blade, click “Query Explorer”. Leave the query as is, i.e.

 

SELECT * FROM c

 

Let’s observe a few things:

  • In the query, c stands for the collection. It is a variable name: you can replace c by whatever literal you fancy
  • The result is a JSON array containing the original documents in each
  • The documents have more “metadata”, i.e. properties starting with _, such as _ts, the timestamp

Let’s try something slightly less trivial:

 

SELECT *
FROM c
WHERE c.firstName != null

 

Now we have only the employees, i.e. we skipped the MTL office document.

The following query does a projection or a JSON transformation:

 

SELECT
{"firstName":c.firstName, "lastName":c.lastName} AS name,
c.office
FROM c
WHERE c.firstName!=null

 

This yields the following results:

[
{
 "name": {
 "firstName": "Vincent-Philippe",
 "lastName": "Lauzon"
 },
 "office": "MTL"
 },
 {
 "name": {
 "firstName": "John",
 "lastName": "Smith"
 },
 "office": "Calgary"
 }
]

 

This demonstrates how DocumentDB merges the power of T-SQL with the JavaScript language seamlessly.

To explore more about querying, go to the querying playground where you can explore interactively (web browser).

Indexing Policy

To look at the current indexing policy of a collection, in the collection blade, click “Indexing Policy”. Typically, you’ll see the following:

 

{
 "indexingMode": "consistent",
 "automatic": true,
 "includedPaths": [
 {
 "path": "/*",
 "indexes": [
 {
 "kind": "Range",
 "dataType": "Number",
 "precision": -1
 },
 {
 "kind": "Hash",
 "dataType": "String",
 "precision": 3
 },
 {
 "kind": "Spatial",
 "dataType": "Point"
 }
 ]
 },
 {
 "path": "/\"_ts\"/?",
 "indexes": [
 {
 "kind": "Range",
 "dataType": "Number",
 "precision": -1
 },
 {
 "kind": "Hash",
 "dataType": "String",
 "precision": 3
 }
 ]
 }
 ],
 "excludedPaths": []
}

 

where you can observe

  • Indexing is consistent (done synchronously with changes)
  • Indexing is automatic
  • Includes all properties
  • Numbers have range indexes, strings hashes and point spatial
  • Timestamp are both range & hash
  • No paths are excluded

Looking at consistency level

Go in you DocumentDB account blade, at the bottom, in “Configuration”, click “Default consistency”.

You can actually see the definitions of each level in the portal.

SDK Demo

Start up a new Console App project. Get the NuGet package Microsoft.Azure.DocumentDB.

Everything orbits around the DocumentClient component. To instantiate one, you need information from your DocumentDB account. In the account blade, click the key icon.

You’ll need:

  • URI (serviceEndPoint in the SDK)
  • Primary key (authKey in the SDK)

In the code, simply instantiate it as:

private static readonly DocumentClient _docClient = new DocumentClient(
new Uri(ENDPOINT),
AUTH_KEY,
ConnectionPolicy.Default,
ConsistencyLevel.Session);

Here you see that you can override the connection policy (see this post for details) and the consistency level for the connection.

The rest of the code will use the method “QueryAsync” defined in this post.

First, let’s find our collection, in purely scalable way:

 

private async static Task<DocumentCollection> GetCollectionAsync()
 {
 var dbQuery = from db in _docClient.CreateDatabaseQuery()
 where db.Id == DB_NAME
 select db;
 var database = (await QueryAsync(dbQuery)).FirstOrDefault();
 var collectionQuery = from col in _docClient.CreateDocumentCollectionQuery(database.AltLink)
 where col.Id == COLLECTION_NAME
 select col;
 var collection = (await QueryAsync(collectionQuery)).FirstOrDefault();
 return collection;
 }

 

What we do here is basically search our database among databases within the account by querying the database list, then do the same thing with collection.
The interesting points to notice here is that we do everything async, including querying. There is nothing blocking here.
Let’s define an employee object, a PONO:
public class Employee
 {
 [JsonProperty("id")]
 public string ID { get; set; }

 [JsonProperty("firstName")]
 public string FirstName { get; set; }

 [JsonProperty("lastName")]
 public string LastName { get; set; }

 [JsonProperty("office")]
 public string Office { get; set; }

 [JsonProperty("phoneNumber")]
 public string PhoneNumber { get; set; }
 }
Here we use attributes to map property names to bridge the gap of JavaScript and C# in terms of naming convention, i.e. the fact that JavaScript typically starts with lowercase while C# starts with uppercase. Other approach could have been used.
Let’s define a method to find me:

 

private async static Task<Employee> QueryVinceAsync(DocumentCollection collection)
 {
 var employees = from e in _docClient.CreateDocumentQuery<Employee>(collection.SelfLink)
 where e.FirstName == "Vincent-Philippe"
 select e;
 var vincent = (await QueryAsync(employees)).FirstOrDefault();
 return vincent;
 }

 

Here, we again do a query, this time on documents within a collection. We strong type the query for employee’s type. That doesn’t filter out non-employees though. The filter on the query does that: it searches for document having a property firstName being equaled to Vincent-Philippe. Document without such a property obviously fail that filter.
Then we can look at the code of the demo:

 

private static async Task DemoAsync()
 {
 var collection = await GetCollectionAsync();
 var vincent = await QueryVinceAsync(collection);
 var newEmployee = new Employee
 {
 FirstName = "Jessica",
 LastName = "Jones",
 Office = "Hell's Kitchen",
 PhoneNumber = "Unknown"
 };
 var newEmployeeResponse =
 await _docClient.CreateDocumentAsync(collection.SelfLink, newEmployee);
 // ID of the created employee document
 Console.WriteLine(newEmployeeResponse.Resource.Id);
 }

 

Interesting point here is the return type of document creation method. Since the SDK is a thin wrapper around REST calls, the return type returns all the stuff returned by the REST call. Of interest: newEmployeeResponse.RequestCharge. This is 6.1 and this is in Request Units (RUs). This helps you figure out the pricing tier you should look after.

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s