npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@agconnections/ottoman

v3.1.1

Published

ODM for Couchbase Node.js driver.

Downloads

25

Readme

Ottoman.js (Node.js ODM for Couchbase)

Ottoman is a ODM built for Couchbase and Node.js. It is designed to remove all of the boilerplate necessary to build Node.js apps with Couchbase.

This is an Ag Connections fork of Ottoman meant to temporarily hold us over until the next version of ottoman is released by couchbaselabs.

Note that the NPM_TOKEN variable in the .npmrc will cause any npm commands to fail unless you have set NPM_TOKEN to your own npmjs token. See this link for details. https://stackoverflow.com/questions/39261943/is-it-possible-to-override-a-local-npmrc-when-running-npm-install

Build Status

Useful Links

Source - http://github.com/agconnections/ottomanjs

Documentation - http://ottomanjs.com/

Build Your First Application - /docs/first-app.md

Couchbase Node.js Community - http://couchbase.com/communities/nodejs

Why Use Ottoman

An ODM allows developers to:

  • Work natively with JavaScript Objects.
  • Rapidly prototype and define your data model together with their relationships.
  • Let someone else handle the heavy lifting and tedious tasks.
  • Support many different data-types, including several which come predefined with Ottoman in addition to support for custom data-types.
  • Define your validation logic with the models it applies to.
  • Model your data for embedding objects or references and keep those relationships crisp.
  • Provide support for generic finds.
  • Support for multiple indexing strategies natively and automatically.
  • Control and enforce your data model from within your application.
  • Programmatically define object methods that map to the data model.

Getting Started

Installing

AgConnections' ottoman is published to npm, to install it in the project, run:

npm install @agconnections/ottoman

Introduction

Set up your Ottoman instance with a connection to Couchbase.

var ottoman = require('ottoman');
var couchbase = require('couchbase');
var cluster = new couchbase.Cluster('couchbase://127.0.0.1');
ottoman.bucket = cluster.openBucket('default');

Let's say we want to track all of the furniture in our store. Let's create a model to represent this furniture.

var Furniture = ottoman.model('Furniture', {
  name: 'string'
});

How about we create our first furniture item.

var couch = new Furniture({name:'Couch'});
console.log(couch.name); // 'Couch'

We can also add methods directly to our models.

Furniture.prototype.dance = () => {
  console.log('I am furniture, I do not dance.');
};

Our furniture now can take an action!

var table = new Furniture({name:'Table'});
table.dance();

But we haven't actually saved anything to Couchbase yet. Let's do that:

table.save((err) => {
  if (err) return console.error(err);
  table.dance();
});

Now that we've saved our table to the database, we need to be able to retrieve it. Let's revise our model to add an index on the name!

var Furniture = ottoman.model('Furniture', {
  name: 'string'
}, {
  index: {
    findByName: {
      by: 'name'
    }
  }
});

Now we need to ensure that this index is available on the server for searching:

ottoman.ensureIndices((err) => {
  if (err) return console.error(err);
});

And finally we can search for our furniture by name:

Furniture.findByName('table', function(err, tables) {
  if (err) return console.error(err);
  console.log(tables);
})

Nice Job!

We've now created our first model, gave it some methods, saved it to Couchbase and then retrieved it.

What Next?

Now that you've successfully built your first models, why not give our full application tutorial a try?

Build Your First Application

Schemas

Schemas define the layout of our stored data objects. They contain a list of properties for the document. This can be any JSON representable data.

You can store simple types:

ottoman.model('User', {
    who: 'string',
    howmany: 'number',
    when: 'Date'
});

Ottoman supports a number of standard types:

  • string - A string value.
  • number - A floating point value.
  • integer - An integer number.
  • boolean - A boolean value.
  • Date - A date value.
  • Mixed - Any valid Ottoman type, both models and built-in types.

These simple types can have default values specified or default value generators:

ottoman.model('User', {
  title: {type: 'string', default: 'No Title'},
  when: {type: 'Date', default: Date.now},
  rander: {type: 'number', default: function(){ return Math.random(); }}
});

We can also have arrays:

ottoman.model('User', {
  name: 'string',
  roles: ['string']
});

And groups:

ottoman.model('User', {
  name: {
    first: 'string',
    last: 'string',
    full: 'string'
  }
});

And arrays of groups:

ottoman.model('User', {
  name: 'string',
  roles: [{
    type: 'string',
    permissions: ['string']
  }]
});

You can also define validator functions for model fields:

function PhoneValidator(val) {
  var phoneno = /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/;
  if (val && !val.match(phoneno)) {
    throw new Error('Phone number is invalid.');
  }
}

ottoman.model('User', {
  name: 'string',
  phone: { type:'string', validator:PhoneValidator },
});

Model References

In addition to supporting groups of properties, models also support referencing whole other documents. Through these references we are able to store related but not necessarily dependent data.

Example reference relationship:

var Account = ottoman.model('Account', {
  email: 'string',
  name: 'string'
});
ottoman.model('User', {
  username: 'string',
  account: Account
});

Accessing the data of a referenced document is as simple as requesting the parent document; referenced documents will be loaded by default.

Example of creating a referenced document:

var myAccount = new Account({
  email: '[email protected]',
  name: 'Brett Lawson'
});
var myUser = new User({
  username: 'brett19',
  account: myAccount;
});
myUser.save((err) => {
  if (err) throw err;

  console.log('Documents Saved!');
});

Example of accessing the referenced document:

User.find({username: 'brett19'}, function(err, myUser) {
  if (err) throw err;

  console.log('My Email:', myUser.account.email);
  // My Email: [email protected]
});

Indices

You can specify numerous indices on a model. There are multiple different kinds of indices, each with it's own benefits and restrictions.

To specify indices on a model, pass a second "options" object to the model function, with an index key:

ottoman.model('User', {
  email: 'string',
  name: {
    first: 'string',
    last: 'string',
    full: 'string'
  }
}, {
  index: {
    findByEmail: {
      by: 'email',
      type: 'refdoc'
    },
    findByFirstName: {
      by: 'name.first',
      type: 'view'
    },
    findByLastName: {
      by: 'name.last',
      type: 'n1ql'
    }
  }
});

In order for indices to be created on the server, you must call the ensureIndices method. This method will internally generate a list of indexes which will be used and the most optimal configuration for them and build any which are missing on the server. This must be called after all models are defined, and it is a good idea to only call this when needed rather than any time your server is started.

var ottoman = require('ottoman');
var models = require('./all_my_models');
ottoman.ensureIndices((err) => {
  if (err) {
    console.log('failed to created necessary indices', err);
    return;
  }

  console.log('ottoman indices are ready for use!');
});

Index Types

Below are some quick notes on the types of indices available, and their pros and cons. For a more in-depth discussion, consider reading Couchbasics: How Functional and Performance Needs Determine Data Access in Couchbase

refdoc

These indices are the most performant, but the least flexible. They allow only a single document to occupy any particular value and do direct key-value lookups using a referential document to identify a matching document in Couchbase.

In short, if you need to look up a document by a single value of a single attribute quickly (e.g. key lookups), this is the way to go. But you cannot combine multiple refdoc indexes to speed up finding something like "all customers with first name 'John' last name 'Smith'".

view

These indices are the default and use map-reduce views. This type of index is always available once ensureIndices is called and will work with any Couchbase Server version.

Because views use map-reduce, certain types of queries can be faster as the query can be parallelized over all nodes in the cluster, with each node returning only partial results. One of the cons of views is that they are eventually consistent by default, and incur a performance penalty if you want consistency in the result.

n1ql

These indices utilize the new SQL-like query language available in Couchbase Server 4.0.0. These indices are more performant than views in many cases and are significantly more flexible, allowing even un-indexed searches.

N1QL indexes in Ottoman use Couchbase GSIs. If you need flexibility of query and speed, this is the way to go.

Queries

Queries allow you to perform searches among your models. For instance allowing you to query all of the posts published by a particular user.

User/Post example:

ottoman.model('Post', {
  user: {ref:'User'},
  title: 'string',
  body: 'string'
});

ottoman.model('User', {
  name: 'string'
}, {
  queries: {
    myPosts: {
      of: 'Post',
      by: 'user'
    }
  }
});

Finding models via N1QL Queries

All models also expose a find method that can locate model instances by any number of criteria, and that also support pagination.

This method is very useful for finding model instances under any arbitrary criteria; however keep in mind that you may wish to put N1QL indexes on fields that would be very often a part of these queries, to improve lookup performance, and prevent Couchbase from having to scan most or all documents in the bucket in order to find the results.

As you can see in the example below, you can even optionally specify pagination (limit/skip) and adjust the consistency of the query executed on Couchbase.

var filters = { 
  lastName: 'Smith',
  state: 'VA'
};

var options = {
  limit: 10,
  skip: 10,
  consistency: ottoman.Consistency.LOCAL,
  sort: {
    state: true, // the boolean true or the number 1 causes ASCENDING sort order
    lastName: 'true' // Any other value causes DESCENDING sort order
  }
};

Customer.find(filters, options,  
  function(err, items) {
    if (err) throw err;

    console.log('Page 2 of Smiths of Virginia: ', JSON.stringify(items));
  });

License

Copyright 2013 Couchbase Inc.

Licensed under the Apache License, Version 2.0.

See the Apache 2.0 license.