Showing posts with label views. Show all posts
Showing posts with label views. Show all posts

Tuesday, October 1, 2013

Pagination with Couchbase

If you have to deal with a large number of documents when doing queries against a Couchbase cluster it is important to use pagination to get rows by page. You can find some information in the documentation in the chapter "Pagination", but I want to go in more details and sample code in this article.


For this example I will start by creating a simple view based on the beer-sample dataset, the view is used to find brewery by country:

function (doc, meta) {
  if (doc.type == "brewery" && doc.country){
   emit(doc.country);
  } 
}


This view list all the breweries by country, the index looks like:

Doc idKeyValue
bersaglierArgentinanull
cervecera_jeromeArgentinanull
brouwerij_nacional_balashiArubanull
australian_brewing_corporationAustralianull
carlton_and_united_breweriesAustralianull
coopers_breweryAustralianull
foster_s_australia_ltdAustralianull
gold_coast_breweryAustralianull
lion_nathan_australia_hunter_streetAustralianull
little_creatures_breweryAustralianull
malt_shovel_breweryAustralianull
matilda_bay_brewingAustralianull
.........
.........
.........
yellowstone_valley_brewingUnited Statesnull
yuengling_son_brewingUnited Statesnull
zea_rotisserie_and_breweryUnited Statesnull
fosters_tien_gangViet Namnull
hue_breweryViet Namnull


So now you want to navigate in this index with a page size of 5 rows.

Monday, April 29, 2013

Screencast : Fun with Couchbase, MapReduce and Twitter

I have created this simple screencast to show how you can, using Couchbase do some realtime analysis based on Twitter feed.

The key steps of this demonstration are

  1. Inject Tweets using a simple program available on my Github Couchbase-Twitter-Injector
  2. Create views to index and query the Tweets by
    • User name
    • Tags
    • Date
The views that I used in this demonstration are available at the bottom of this post.



Views:

Wednesday, February 13, 2013

Introduction to Collated Views with Couchbase 2.0


Most of the applications have to deal with "master/detail" type of data:

  • breweries and beer
  • department and employees
  • invoices and items 
  • ...
This is necessary for example to create application view like the following:

With Couchbase, and many of the document oriented databases you have different ways to deal with this, you can:
  • Create a single document for each master and embed all the children in it
  • Create a master and child documents and link them using an attribute.
In the first case when all the information are stored in a single document it is quite easy to use the entire set of data and for example create a screen that shows all the information, but what about the second case?

In this post I am explaining how it is possible to use Couchbase views to deal with that an make it easy to create master/detail views.

As an ex-Oracle employee, I am using the infamous SCOTT schema with the DEPT and EMP tables, as the first example. Then at the end I will extend this to the beer sample data provided with Couchbase.

The Data

Couchbase is a schema-less database, and you can store “anything you want” into it, but for this you need to use JSON documents and create 2 types of document : “department” and “employee”.

The way we usually do that is using a technical attribute to type the document. So the employee and department document will look as follow :

Department
{
  "type": "dept",
  "id": 10,
  "name": "Accounting",
  "city": "New York"
}
Employee
{
  "type": "emp",
  "id": 7782,
  "name": "Blake",
  "job": "Clark",
  "manager": 7839,
  "salary": 2450,
  "dept_id": "dept__10"
}

This shows just the document, in Couchbase you have to associate a document to a key. For this example I am using a simple pattern : type__id , for these documents the keys will look like the following:
  • dept__10
  • emp__20

You can use any pattern to create a key, for example for the employee you could chose to put an email.  

Note the “dept_id” attribute in the employee document. This is the key of the department; you can see that as the “foreign key”. But remember, the relationship between the department and employee documents are managed entirely by the application, Couchbase Server does not enforce it.

I have created a Zip file that contains all the data, you can download it from here; and import the data into Couchbase using the cbdocloader utility. To import the data run the following command from a terminal window:

./cbdocloader -n 127.0.0.1:8091 -u Administrator -p password -b default ~/Downloads/emp-dept.zip 

You can learn more about the cbdocloader tool in the documentation.

The View

Queries inside Couchbase are based on views; and views build indexes, so we have to create a view, a "collated view" to be exact.

The idea behing a collated view is to produce an index where the keys are ordered so that a parent id appears first followed by its children.  So we are generating an index that will look like:

DEPT_10, Accounting
DEPT_10, Blake
DEPT_10, Miller
DEPT_20, Research
DEPT_20, Adams
DEPT_20, Ford
...


This is in fact quite easy to do with Couchbase views. The only trick here is to control the order and be sure the master is always the first one, just before its children.

So to control this we can create an compound key that contains the department id, a "sorting" element and the name (beer or brewery)

So the map function of the view looks like the following:

The key is composed of:
  • the department id extracted from the department document itself or from the employee document depending of the type of document
  • an arbitrary number that is used to control the ordering. I put 0 for the department, 1 for the employee
  • the name of the department or the employee, this also allows to sort the result by name
In addition to the key, this view is used to emit some information about the salary of the employees. The salary is simply the sum of the salary plus the commission when exists. The result of the view looks like:

With this view you can now use the result of the view to build report for your application. It is also possible to use parameters in your query to see only a part of the data, for example by departement, using for example startkey=["dept__20",0]&endkey=["dept__20",2] to view only the data -Department and Employees- of the deparment 20-Research.


The Beer Sample Application

You can create an equivalent view for the beer sample application where you print all the breweries and beers in the same report. The view is called "all_with_beers" in the design document "brewery". The view looks like:


Once you have publish it in production you can use it in the Beer Sample application, for this example I have modified the Java sample application.

Create a servlet to handle user request and on the /all URI.

The "BreweryAndBeerServlet" that calls the view using the following code :


The result of the query is set into the HttpRequest and the all.jsp page is executed. The JSP uses JSTL to print the information using the following code:
The JSP gets the items from the HTTP Request and loops on each items, then based on the type of the item the information is printed. The final result looks like :



This extension to the Beer Sample application is available here : https://github.com/tgrall/beersample-java/tree/BreweriesAndBeers

Sunday, December 30, 2012

Couchbase 101: Create views (MapReduce) from your Java application

When you are developing a new applications with Couchbase 2.0, you sometimes need to create view dynamically from your code. For example you may need this when you are installing your application, writing some test, or you can also use that when you are building frameworks, and wants to dynamically create views to query data. This post shows how to do it.

Prerequisites

If you are using Maven you can use the following information in your pom.xml to add the Java Client library:

  
    
      couchbase
      Couchbase Maven Repository
      default
      http://files.couchbase.com/maven2/
      
        false
      
    
  
  
  
    
      couchbase
      couchbase-client
      1.1.0
      jar
    
  
See online at https://gist.github.com/4337172

Create and Manage Views From Java 

The full Maven project is available on Github.

Connect to Couchbase Cluster

The first thing to do when you want to create a view from Java is obviously to connect to the cluster.

import com.couchbase.client.CouchbaseClient;
...
...

    List uris = new LinkedList();
    uris.add(URI.create("http://127.0.0.1:8091/pools"));
    CouchbaseClient client = null;
    try {
        client = new CouchbaseClient(uris, "beer-sample", "");

        // put your code here

        client.shutdown();      

    } catch (Exception e) {
        System.err.println("Error connecting to Couchbase: " + e.getMessage());
        System.exit(0);
    }

...
...

  1. Create a list of URIs to different nodes of the cluster - lines 5-6. (In this example I am working on a single node)
  2. Connect to the bucket, in our case beer-sample -line 9. You can include the password if the bucket is protected ( this is not the case here so I am sending an empty string)
If you are looking for more information about Couchbase and Java, you can read this article from DZone : Hello World with Couchbase and Java.

Let's now talk about Couchbase views. You use views/map-reduce functions to index and query data from Couchbase Server based on the content of the JSON document you store inside Couchbase. For more information about views you can look at the "view basics" chapter of the Couchbase Server Manual.

Create Views from Java

Creating a view from Java is really easy : the Java Client Library contains all the classes and methods to do it. As a concrete use case we will use the Application that is described in the Couchbase Java Tutorial.

When you follow this tutorial, you need to manually create some views, as you can see here. In this example, we will create our map function and directly in our Java code and then store it to Couchbase Server. The tutorial asks you to create the following artifacts:
  • a view named "by_name
  • in the design document named "dev_beer" (development mode)
  • and the map function which looks like the following :
 function (doc, meta) {
   if(doc.type && doc.type == "beer") {
     emit(doc.name, null);
   }
 }


The following code allows you to do it from Java:

import com.couchbase.client.protocol.views.DesignDocument;
import com.couchbase.client.protocol.views.ViewDesign;
...
    DesignDocument designDoc = new DesignDocument("dev_beer");

    String viewName = "by_name";
    String mapFunction =
            "function (doc, meta) {\n" +
            "  if(doc.type && doc.type == \"beer\") {\n" +
            "    emit(doc.name);\n" +
            "  }\n" +
            "}";

    ViewDesign viewDesign = new ViewDesign(viewName,mapFunction);
    designDoc.getViews().add(viewDesign);
    client.createDesignDoc( designDoc );
...


  • Create a design document using the com.couchbase.client.protocol.views.DesignDocument class - line 4.
  • Create a view using com.couchbase.client.protocol.views.ViewDesign class with a name and the map function - line 14.
  • You can add this view to a design document - line 15
  • Finally save the document into the cluster using the CouchbaseClient.createDesignDoc method.
If you need to use a reduce function (built-in or custom) you just need to pass to the ViewDesign constructor as 3rd parameter.

When developing view, from Java or from any other tool/language be sure you understand what are the best practices, and the life cycle of the index. This is why I am inviting you to take a look to the following chapters in the Couchbase documentation:

Using the view

First of all, the view that you just created is in "development mode", and by default the Java client SDK will only access the view when it is in "production mode". This means that when you are calling a view from your application it will search it into the production environment. So before connecting to Couchbase cluster you need to setup the viewmode to development.

This is done using the viewmode environment variable from the Java SDK, that could be set using the following methods:
  • In your code, add this line before the client connects to the cluster : System.setProperty("viewmode", "development");
  • At the command line -Dviewmode=development
  • In a properties file viewmode=development
Once it is done you can call the view using the following code:
import import com.couchbase.client.protocol.views.*;

...
   System.setProperty("viewmode", "development"); // before the connection to Couchbase
...
   View view = client.getView("beer", "by_name");
   Query query = new Query();
   query.setIncludeDocs(true).setLimit(20);
   query.setStale( Stale.FALSE );
   ViewResponse result = client.query(view, query);
   for(ViewRow row : result) {
     row.getDocument(); // deal with the document/data
   }
...

This code queries the view you just created. This means Couchbase Server will generate an index based on your map function, will query the server for results. In this case, we specifically want to set a limit of 20 results and also get the most current results by setting Stale.FALSE.
  • Set the viewmode to development - line 4
  • Get the view using the CouchbaseClient.getView() method -line 6-. As you can see I just use the name beer for the design document (and not dev_beer, Couchbase will know where to search since I am in development mode)
  • Create a query and set a limit (20) and ask the SDK to return the document itself
    setIncludeDocs(true) -line 8- The document will be returned from Couchbase server in the most efficient way
  • Ask the system to update the index before returning the result using query.setStale( Stale.FALSE ); -line 9-. Once again be careful when you use setStale method. Just to be sure here is the documentation about it : Index Updates and the stale Parameter
  • Execute the query - line 10
  • And use the result - lines 11-13

Conclusion

In this article, you have learned:
  • How to create Couchbase views from Java
  • Call this view from Java
  • Configure development/production mode views from Couchbase Java Client Library
This example is limited to the creation of a view, you can take a look to the other methods related to design documents and views if you want to manage your design documents : getDesignDocument(), deleteDesignDocument(), ... .