Introduction to CouchDB with .NET part 15: show functions in design documents

Introduction

In the previous post we took a look at lists in CouchDB design documents. Lists operate in conjunction with views. A list function has access to the output of a view and can transform it into a different data set. Lists do not change the underlying data at all, they are a type of extension to views. A list can output simple JSON or advanced HTML for fancy reports. We have access to the HTTP request object within the list function. The output of a list function can thus depend on stuff like query parameters, request headers, cookies etc.

In this post we’ll look at another function type in design documents called show functions.

Shows

Show functions are also JavaScript functions within a design document like the other function types we’ve seen before. As opposed to lists a show function doesn’t require the output from a view. Instead, it operates on a single document. A show function accepts two parameters:

  • The document which was extracted based on the provided in the URL. This can be null if no document is found by the provided ID so the show function should be prepared to deal with that case.
  • The HTTP request object which is the same kind of object we saw in the previous function.

Show functions can also return simple strings and formatted HTML like lists.

We created a database called “players” with 4 documents in the previous post. We’ll reuse it but here’s a reminder of its content:

{
  "name": "John",
  "yearOfBirth": 1980,
  "scoreBase": 100
}

{  
  "name": "Jane",
  "yearOfBirth": 1987,
  "scoreBase": 110
}

{  
  "name": "Mary",
  "yearOfBirth": 1989,
  "scoreBase": 95
}

{
  "name": "Peter",
  "yearOfBirth": 1988,
  "scoreBase": 105
}

A first simple example

Add the following design document to the players database:

{
  "_id": "_design/show-demos",
  "shows": {
    "to-string": "function(document, request) { if (document) { return 'This is ' + document.name + ', born in ' + document.yearOfBirth + ' with base points of ' + document.scoreBase;} else { return 'No such document'; } }"
  }
}

Show functions are included within the “shows” section of a design document. As mentioned above, a show function accepts the document and the HTTP request in its signature. We first check if the document was found. If that’s the case then we simply return a string with its properties. Otherwise we tell the user that there’s no such document.

We use the following URL template to call show functions:

GET /_design/{design-doc-id}/_show/{show-function-name}/{document-id}

The player “Peter” has ID 3031afee194a8e4295c021221a014306 in my case so the URL would look like the following:

GET http://localhost:5984/players/_design/show-demos/_show/to-string/3031afee194a8e4295c021221a014306

It duly returns “This is Peter, born in 1988 with base points of 105”.

If there’s no document found then we’ll see “No such document” in the response.

Returning JSON

It’s easy to return JSON by providing the ‘json’ type in the return argument as follows:

"to-string-json": "function(document, request){ var name = 'N/A'; var birthYear = 'N/A'; var score = 'N/A'; if (document) { name = document.name; birthYear = document.yearOfBirth; score = document.scoreBase; } return { 'json': { 'name': name, 'birth-year': birthYear, 'score': score }}}"

Here’s the JS function in a more readable format:

function(document, request) {
	var name = 'N/A';
	var birthYear = 'N/A';
	var score = 'N/A';
	if (document) {
		name = document.name;
		birthYear = document.yearOfBirth;
		score = document.score;
	}
	
	return {
		'json': {
			'name': name,
			'birth-year': birthYear,
			'score': score
		}
	}
}

We execute the show function as follows:

GET http://localhost:5984/players/_design/show-demos/_show/to-string-json/3031afee194a8e4295c021221a014306

…which returns…

{"name":"Peter","birth-year":1988,"score":105}

…if the document is found, otherwise we’ll see the following:

{"name":"N/A","birth-year":"N/A","score":"N/A"}

Return HTML

We can embed HTML tags in the output:

"to-string-html": "function(document, request) { var name = 'N/A'; var birthYear = 'N/A'; var score = 'N/A'; if (document) {name = document.name; birthYear = document.yearOfBirth; score = document.scoreBase; } return { body: '<html><body><table><tr><th>Name</th><th>Birth year</th><th>Score</th></tr><tr><td>' + name + '</td><td>' + birthYear + '</td><td>' + score + '</td></tr></table></body></html>', headers: { 'Content-Type': 'text/html' }}}"

Here’s the formatted JS function:

function(document, request) {
    var name = 'N/A';
    var birthYear = 'N/A';
    var score = 'N/A';
    if (document) {
        name = document.name;
        birthYear = document.yearOfBirth;
        score = document.score;
    }
    return {
        body: '<html><body><table><tr><th>Name</th><th>Birth year</th><th>Score</th></tr><tr><td>' + name + '</td><td>' + '</td><td>' + birthYear + '</td><td>' + score + '</td></tr></table></body></html>',
        headers: {
            'Content-Type': 'text/html'
        }
    }
}

Note how we return a JSON object with two members:

  • Body: this can be any body type, a simple string or embedded HTML like in the example above
  • Headers: we can set standard and custom headers here

The document properties are now rendered in a HTML table:

Show function renders HTML in CouchDB

Returning a JSON object with these two properties is not a must, we could have returned the HTML string like in the first demo as well.

Variable return MIME types

The request can indicate which MIME type it wants in the Accept header. Typical values include text/html, application/xml. The show function can return multiple formats depending on what the client requested. Even custom accept headers can be registered and handled. Here’s an example:

"to-string-multi": "function(doc, req){ provides('json', function(){ return {'json': doc}}); provides('html', function(){ return '<pre>' + toJSON(doc) + '</pre>'});registerType('text-custom', 'text/custom'); provides('text-custom', function(){ return '<custom>' + toJSON(doc) + '</custom>';})}"

Here’s the JS function:

function(doc, req) {
    provides('json', function() {
        return {
            'json': doc
        };
    });
    provides('html', function() {
        return '<pre>' + toJSON(doc) + '</pre>';
    });
    registerType('text-custom', 'text/custom');
    provides('text-custom', function() {
        return '<custom>' + toJSON(doc) + '</custom>';
    })
}

There are two functions to be noted:

  • provides: it accepts a return format like JSON or HTML and a function which declares what is to be returned if those MIME types are requested
  • registerType: we can register our custom MIME type. The function accepts an ID for later use in the provides function. It also accepts the value of the Accept header, in this case ‘text/custom’

If we execute this show function in a browser it will respond with the HTML format of course:

GET http://localhost:5984/players/_design/show-demos/_show/to-string-multi/3031afee194a8e4295c021221a014306

<pre>
{"_id":"3031afee194a8e4295c021221a014306","_rev":"2-0cac638a31eff93ec262ecedff73b851","name":"Peter","yearOfBirth":1988,"scoreBase":105,"_revisions":{"start":2,"ids":["0cac638a31eff93ec262ecedff73b851","14f4f7b938e183dffa29c41ee1f9c29c"]}}
</pre>

Read the next part here.

You can view all posts related to data storage on this blog here.

Advertisements

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

One Response to Introduction to CouchDB with .NET part 15: show functions in design documents

  1. Pingback: CouchDB Weekly News, June 22, 2017 – CouchDB Blog

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

ultimatemindsettoday

A great WordPress.com site

Elliot Balynn's Blog

A directory of wonderful thoughts

Robin Sedlaczek's Blog

Developer on Microsoft Technologies

HarsH ReaLiTy

A Good Blog is Hard to Find

Softwarearchitektur in der Praxis

Wissenswertes zu Webentwicklung, Domain-Driven Design und Microservices

the software architecture

thoughts, ideas, diagrams,enterprise code, design pattern , solution designs

Technology Talks

on Microsoft technologies, Web, Android and others

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

Anything around ASP.NET MVC,WEB API, WCF, Entity Framework & AngularJS

Cyber Matters

Bite-size insight on Cyber Security for the not too technical.

Guru N Guns's

OneSolution To dOTnET.

Johnny Zraiby

Measuring programming progress by lines of code is like measuring aircraft building progress by weight.

%d bloggers like this: