Introduction to CouchDB with .NET part 16: update functions in design documents

Introduction

In the previous post we saw how show functions work in design documents. Show functions are applied on a single document and are able to transform that document into a different format. The formats can range from simple string manipulations to HTML reports. The show function has access to the HTTP request as well with its rich object which contains the request headers, the cookies, the query parameters and much more. Therefore the HTTP request can also be used to refine the logic within a show function.

In this post we’ll look at the last remaining design document function type called update functions.

Update functions

Update functions are functions that can be called to update a document without bothering about the revision ID. The function must be called with a PUT request, i.e. it is not executed automatically upon a document update. An update function has access to the following parameters:

  • The document being updated which was retrieved using the ID in the PUT request
  • The HTTP request which is the same object we saw in list and show functions

The update function can be as simple as adding an extra row to a document. It can also be more complex that depends on the HTTP request parameter and modifies the document properties based on some logic. The one key takeaway here is that an update function is not applied automatically, the client must call upon it actively through a HTTP request. Update functions also return a HTTP response.

We’ll use the same “players” database for the demo as for the list and show functions. 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
}

Demo

We’ll add a date to the document called last_updated. We’ll also add the requested URL path to see how we can invoke the HTTP request object Add the following design document to the players database:

{
  "_id": "_design/updates",
  "updates": {
    "last-updated": "function(document, request) {if (document != null) {var date = new Date(); document['last_updated']=date; document['path'] = request.raw_path; return [document, 'Added the requested fields'];} return [null, 'No such document'];}"
  }
}

Here’s the JS function:

function(document, request) {
    if (document != null) {
        var date = new Date();
        document['last_updated'] = date;
        document['path'] = request.raw_path;
        return [document, 'Added the requested fields'];
    }
    return [null, 'No such document'];
}

If the document is found, i.e. is not null, then we add the two new fields to it. If the fields exist then they are updated. We finally return a message to the client. If the document doesn’t exist then we return a null object and a different message.

Here’s the URL template to call an update function:

PUT /_design/{design-doc-id}/_update/{update-function-name}/{doc-id-to-be-updated}

The player Mary has ID 3031afee194a8e4295c021221a013327 in my case so the full URL will be the following:

PUT http://localhost:5984/players/_design/updates/_update/last-updated/3031afee194a8e4295c021221a013327

It responds with “Added the requested fields” in the body. It looks like Mary was in fact successfully updated:

{
  "_id": "3031afee194a8e4295c021221a013327",
  "_rev": "5-f470b03d590df83ab0fc55377dfd35d2",
  "name": "Mary",
  "yearOfBirth": 1989,
  "scoreBase": 95,
  "last_updated": "2017-06-11T07:55:56.524Z",
  "path": "/players/_design/updates/_update/last-updated/3031afee194a8e4295c021221a013327"
}

The revision ID is automatically updated.

Update functions can potentially replace the way we updated documents before through the HTTP API. We can send any JSON payload in the request which in turn can be extracted through the request.body property. We then read those values from the JSON and change the properties of the retrieved documents. There’s no need to send the properties that don’t want to modify. We can also apply any extra logic like “updated-by” and read the principal from the HTTP request. That way we know who has updated the document.

The major benefit of an update function is that we don’t need to bother with the latest revision ID, the function will get it for us. Also, we don’t need to send in all properties of the document in the JSON body, only the ones that should be updated.

Read the next part here where we start discussing Mango queries.

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

Advertisement

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

3 Responses to Introduction to CouchDB with .NET part 16: update functions in design documents

  1. Harold says:

    Great series of blogposts! What I’m wondering the most about NoSQL solutions like CouchDB is how to handle duplicate data? In SQL you would prevent duplicate data with relations. But how to handle this in NoSQL? For example a person will write multiple blogposts and news articles and puts comments on blogposts etc. And then that persons changes her name because she got married. Do I have to update all blogposts and newsarticles and comments myself or can CouchDB help with that?

    • Andras Nemes says:

      Harold, NoSql is schemaless, there’s usually no built-in way to control duplicates, although I can only speak for MongoDB and CouchDB. For CouchDB specifically we have the validation design document where you can implement a logic that checks for duplicate records before letting the modification go through.

      For your other question I think the best strategy is to mimic the table setup of a relational database: posts in one set of documents and authors in another and link them with the user ID in an approximation of the secondary key. That way you only have to change the user’s name in one place. There are no JOINs so you’ll have to deal with populating the full data set when reading the posts and attach the user’s name to be displayed on the screen.

      So while it’s true that NoSql documents can include a wide range of documents, sub-documents and sub-documents of sub-documents use that feature wisely. Separate out those documents that you think can change over time and are important for querying and indexing.

      //Andras

  2. 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 )

Connecting to %s

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

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

%d bloggers like this: