Performing a first query

As of Couchbase 2.0, you can index and query entries using views. Views are functions you define and use to filter, extract and perform calculations on entries that are persisted in a given data bucket. The functions you create will provide a ‘map’ function, which can filter/extract items based on rules you specify, and may optionally perform a ‘reduce’ function, which can perform calculations and operations across a selected group of entries. There are a few possible ways you can initially store and use views functions as JSON documents:

  • Create and manage using Couchbase Admin Console, or

  • Create and manage using the REST API, or

  • Create, store, and query using your chosen Couchbase SDK.

Since this content is for the developer audience, we will focus here on using the SDKs to perform queries and describe the REST API as an alternative approach.

Imagine in our previous example that we also want to find all the names of users who are under 21. In this scenario we would use a view; in fact we would want to use views in any other scenario where we want to filter entries based on certain field values, or provide lists and tables of certain entries. For this example we provide the map function for you. If you are more familiar with views in Couchbase 2.0, you may notice some missing elements in our map function. For the sake of brevity here and for newcomers to views, we omitted some of the complexity for now:

function (doc) {
    if ( doc.age && doc.name ) {
    if ( doc.age < 21 ) { emit(doc.name, doc.age) };
  }
}

You may not have used JavaScript before, but if you have used other programming languages such as C, Java, or PHP, this should look familiar to you. This is a standard function definition with one parameter, doc which is a JSON document stored in Couchbase Server.

The key part of this function to understand is the conditional statement if (doc.age < 21 )..... This is how you specify the core logic of your map function. In this case, we are saying that if age field has a value less than 21, we want information from that record extracted and put in the result set. The next part of the code, emit(doc.name, doc.age) indicates when Couchbase Server finds a matching record, it should include value from the name field and should include value from the age field in the result set.

As a best practice we want make sure that the fields we want to include in our index actually exist. Therefore we have our map function within a conditional: if (doc.age && doc.name). This ensures the fields exist in documents when we query the view and we therefore avoid a view failure when Couchbase Server generates the index.

For the sake of convenience, we can store our view in a ‘design document’ and then use a Couchbase SDK to store it from the file. Design documents are JSON documents where we store our views functions as strings; they are stored in Couchbase Server and are associated with a Couchbase Bucket. First we create the design document and include our view function in it:

{
  "_id": "_design/students",
  "language": "javascript",
  "views": {
    "underage": {
      "map": "function(doc) {if (doc.age && doc.name)
{if(doc.age < 21){emit(doc.name, doc.age);}}}"
    }
  }
}

The first two fields indicate the JSON document is a design document named students and it follows the syntax used in JavaScript. The next field is a hash that contains any views and in this case we have one view called underage. Within the view we provide the map function described above. We can store this to the file system as students.json and then write the design document to Couchbase Server using an SDK.

As a best practice we want make sure that the fields we want to include in our index actually exist. Therefore we have our map function within a conditional: if (doc.age && doc.name). This ensures the fields exist in documents when we query the view and we therefore avoid a view failure when Couchbase Server generates the index.

client = Couchbase.connect("http://localhost:8091/pools/default/buckets/newBucket")

client.save_design_doc(File.open('students.json'))

We open the students.json file and then write it to Couchbase Server with the save_design_doc call. Couchbase Server will store a new design document with the key students which is available from our SDK. At this point we can query the view and retrieve matching results:

students = client.design_docs['students']

students.views                    #=> ["underage"]

students.underage

The first things we do is retrieve the design document from Couchbase Server. We do this by first calling design_docs with the named design document students, and then call views to get the views it contains. Finally we perform the query by calling the view, in this case we call underage. Couchbase Server will execute the map function in our view and return this information in the result set:

.... @id="doc1" @key="Aaron" @value=20 ....
.... @id="doc3" @key="Peter" @value=16 ....
.... @id="doc4" @key="Ralf" @value=12 ....

If you go back and look at our map function, we indicate we want to extract doc.name and doc.age. Couchbase Server provides the key for the document containing a matching field value under 21, which is docNum, as well as the name and age of the student. As an alternate approach, you can also store a view in Couchbase Server by using the REST API and then query it using a REST request. To store the view, you would make a REST request as follows:

curl -X PUT -u newBucket:password -H 'Content-Type: application/json' \
 'http://server_ip:8092/newBucket/_design/students' \
-d '{"views": {"underage":{"map":"function(doc) {if(doc.age && doc.name) \
{if(doc.age<21){emit(doc.name, doc.age);}}}"}}}'

We perform the REST request as a put and provide the bucket name and password for that bucket. We indicate the content will be JSON, and the rest endpoint is the Couchbase bucket along with /_design/students. Finally we provide the view as the request payload. After Couchbase Server successfully stores the new design document students with the underage view, it provides a response in JSON:

{"ok":true, "id":"_design/students"}

Now we can query the view by performing a REST request as follows:

curl -X GET -u newBucket:password 'http://server_ip:8092/newBucket/_design/students/_view/underage?'

Couchbase Server responds with the following results as JSON:

{"total_rows":3,"rows":[
{"id":"doc1", "key":"Aaron", "age":20},
{"id":"doc3", "key":"Peter", "age":16},
{"id":"doc4", "key":"Ralf", "age":12}
]
}

This section is intended as a brief introduction to querying and indexing JSON documents with Couchbase SDKs. There is definitely much more to learn about the topic. For more information about using views with the SDKs, see Finding data with views. For general information about Couchbase Server indexes and queries, see Views and indexes.