Install and Start Using the Ottoman ODM with Couchbase Server

    +
    Installing the Ottoman ODM & a Hello World program.

    Ottoman is an open-source Object Document Mapper(ODM) library, built for Node.js and Couchbase, that aspires to give developers an even better experience when building modern applications.

    Ottoman ODM adds an abstraction layer over Couchbase Node.js SDK and significantly reduces the level of boilerplate needed during application development. It provides features such as the ability to define document schemas and perform validations on your data in a NoSQL landscape — which is inherently schema-less or schema-flexible by nature.

    Whether you are building your application with JavaScript or TypeScript, Ottoman will work seamlessly with either.

    Ottoman fully supports the Scopes and Collections features introduced in Couchbase Sever 7.0. We recomend familiarizing yourself with these concepts before proceeding with this guide.

    For a full feature comparison between Ottoman ODM and the Couchbase Node.js SDK you can read more here.

    Creating a New Ottoman Project

    Creating a new Ottoman project is as easy as making a directory and initializing it with npm. The next two commands will do that for us. Open up a terminal and run the following command:

    $ mkdir node-ottoman-project && cd $_

    The command above will create our directory and change the current working directory.

    $ npm init -y

    If a directory does not already have a package.json at its root, this means it is not initialized. The command above will accomplish this.

    Note: We have used the -y flag to take the initialization defaults. To change any of these defaults, just open the package.json and manually make any changes.

    {
      "name": "node-ottoman-project",
      "version": "1.0.0",
      "description": "",
      "main": "index.js",
      "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
      },
      "keywords": [],
      "author": "",
      "license": "ISC"
    }

    Compatibility

    Before installing Ottoman, you will need to ensure that you meet the minimum requirements shown in the compatibility table below:

    Ottoman Node.js Couchbase SDK Couchbase Server

    ^2.0.0

    ^8.0.0

    ^3.2.2

    ^6.5.0

    Installing the Ottoman ODM

    $ npm install ottoman --save

    This will download the latest Ottoman ODM, and add a dependency to your package.json.

    Hello Ottoman

    In the directory we have just created, named node-ottoman-project, let’s create an empty file named index.js. At this point we want to transition from the terminal to your code editor of choice. We will walk through, step by step, adding code to enable us to connect to a bucket, add a document, and retrieve it. First, import Ottoman in your new index.js file:

    const { Ottoman, Schema, SearchConsistency } = require('ottoman')
    const ottoman = new Ottoman()

    For the purposes of this example we will create an async function called main under our imports. This will contain all our example code going forward.

    async function main() {
      // your code goes here...
    }

    Now, let’s create a connection to our Couchbase Server.

      var connection = await ottoman.connect({
        connectionString: 'couchbase://localhost',
        bucketName: 'travel-sample',
        username: 'Administrator',
        password: 'password',
      })

    Note that you can also use the below shorthand when creating a connection:

      connection = await ottoman.connect(
        'couchbase://localhost/travel-sample@Administrator:password'
      )

    Couchbase uses Role Based Access Control (RBAC) to control access to resources. Here we will use the Full Admin role created during installation of the Couchbase Data Platform. For production client code, you will want to use more appropriate, restrictive settings — but here we want to get you up and running quickly.

    Since we are running this locally, we will use the Couchbase alias for localhost.

    If you are not working with the travel-sample data bucket, substitute travel-sample with your bucket name.

    Schemas, Models, and Documents

    Everything in Ottoman starts with a Schema. A Schema maps to a Collection and defines the shape of the documents within that Collection.

    Models in Ottoman are simply constructors compiled from Schema definitions, which help you to easily create, read, update, and delete documents in your Couchbase database. An instance of a model is called a Document.

    First, we’ll define a schema to represent the shape of our data:

      const airlineSchema = new Schema({
        type: String,
        id: Number,
        name: String,
        callsign: String,
        iata: String,
        icao: String,
      })

    Now, we call the model() constructor to build the model based on the schema we just created.

      const Airline = connection.model('airline', airlineSchema, {
        scopeName: 'inventory',
      })

    Notice that the constructor takes arguments like the collection name, schema, and model options. In the model options we can define properties such as scopeName to tell Ottoman which Scope we want to store our data in. In this case we are storing our data in the inventory Scope.

    Before performing any database actions we must call the start() function. This will ensure that the relevant scopes, collections, and indexes have been created in Couchbase.

      await connection.start()

    To persist the data in Couchbase we will need to create a Document object and subsequently call the save() function:

      const airlineDoc = new Airline({
        type: 'airline',
        id: 8091,
        callsign: 'CBS',
        name: 'Couchbase Airways 1',
        icao: 'CBICAO',
        iata: 'CBIATA',
      })
    
      // Persist the airline document we just created in the database
      await airlineDoc.save()
      console.log(`Success: airline ${airlineDoc.name} added!\n`)

    Alternatively, we can also use the create() function to create and save the document:

      await Airline.create({
        type: 'airline',
        id: 8092,
        callsign: 'CBS2',
        name: 'Couchbase Airways 2',
        icao: 'CBICAO2',
        iata: 'CBIATA2',
      })

    Querying Documents

    Querying documents is easy with Ottoman, thanks to the underlying Query Builder built into the ODM. The Query Builder can handle many complex operations supported by Couchbase and N1QL.

    Documents can be retrieved using model helper methods such as find(), findById(), or findOne(). For this example, let’s retrieve one of the airline documents we saved previously with find(), and filter by callsign:

      const result = await Airline.find(
        { callsign: 'CBS' },
        { consistency: SearchConsistency.LOCAL }
      )
      console.log('Query Result: ', result.rows)

    Finally, add this last code snippet after the main function:

    main()
      .catch((error) => console.log('ERR:', error))
      .finally(process.exit)

    Now we can run our code using the following command:

    $ node index.js

    The results you should expect are as follows:

    Success: airline Couchbase Airways 1 added!
    
    Query Result:  [
      _Model {
        callsign: 'CBS',
        iata: 'CBIATA',
        icao: 'CBICAO',
        id: 'airline_8091',
        name: 'Couchbase Airways 1',
        type: 'airline'
      }
    ]

    Full Example

    If you want to copy and paste to run the full example, here it is:

    'use strict'
    
    const { Ottoman, Schema, SearchConsistency } = require('ottoman')
    const ottoman = new Ottoman()
    
    async function main() {
      var connection = await ottoman.connect({
        connectionString: 'couchbase://localhost',
        bucketName: 'travel-sample',
        username: 'Administrator',
        password: 'password',
      })
    
      connection = await ottoman.connect(
        'couchbase://localhost/travel-sample@Administrator:password'
      )
    
      const airlineSchema = new Schema({
        type: String,
        id: Number,
        name: String,
        callsign: String,
        iata: String,
        icao: String,
      })
    
      const Airline = connection.model('airline', airlineSchema, {
        scopeName: 'inventory',
      })
    
      await connection.start()
    
      const airlineDoc = new Airline({
        type: 'airline',
        id: 8091,
        callsign: 'CBS',
        name: 'Couchbase Airways 1',
        icao: 'CBICAO',
        iata: 'CBIATA',
      })
    
      // Persist the airline document we just created in the database
      await airlineDoc.save()
      console.log(`Success: airline ${airlineDoc.name} added!\n`)
    
      await Airline.create({
        type: 'airline',
        id: 8092,
        callsign: 'CBS2',
        name: 'Couchbase Airways 2',
        icao: 'CBICAO2',
        iata: 'CBIATA2',
      })
    
      const result = await Airline.find(
        { callsign: 'CBS' },
        { consistency: SearchConsistency.LOCAL }
      )
      console.log('Query Result: ', result.rows)
    }
    
    main()
      .catch((error) => console.log('ERR:', error))
      .finally(process.exit)

    Additional Resources

    To learn more about Ottoman ODM you can head over to the official Ottoman page. You can also find more in-depth information on some of the topics we touched on:

    If you are evaluating whether to use Ottoman in your next project, the FAQs here should also answer some questions.

    Links to each release are to be found in the individual release notes.

    Couchbase welcomes community contributions to the Ottoman ODM. The Ottoman ODM source code is available on GitHub.