Skip to content
Jon Clausen edited this page Dec 20, 2015 · 6 revisions

Usage

CBMongoDB will inspect your model properties to create your default document schema. All you need to do is add schema=true to your property and it will be included with the default document. You can either use a dot notation in the property name field for nested documents (infinite recursion) or specify parent="myParentProperty" (single-level recursion). For example a contact property might be:

/**Schema Properties**/
property name="first_name" schema=true validate="string";
property name="last_name" schema=true valiate="string";
property name="address" schema=true validate="struct";
/**Use either dot notation in the name or specify a 'parent' attribute as ways of creating nested documents**/
/**Dot Notation Examples**
property name="address.street" schema=true validate="string";
property name="address.city" schema=true validate="string";
property name="address.state" schema=true validate="string" length=2;
property name="address.postalcode" schema=true validate="zipcode";
property name="address.country" schema=true validate="string";
/**Parent attribute**/
property name="phone" schema=true validate="struct";
property name="home" schema=true parent="phone" validate="telephone";
property name="work" schema=true parent="phone" validate="telephone";
property name="mobile" schema=true parent="phone" validate="telephone";

The major difference is that parent notation allows direct usage of the accessor (e.g. this.getMobile() ). Dot notation, however, is more natural with the query syntax and is recommended.

CBMongoDB emulates many of the functions of the cborm ActiveEntity, to make getting started simple. There is also a chainable querying syntax which makes it easy to incorporate conditionals in to your search queries. The following examples assume model inheritance.

Create a new document and then query for (we're maintaining case in this example, but it's not necessary if you've already mapped your schema properties, which maintain case automatically)

var person=this.populate({
	'first_name'='John',
	'last_name'='Doe',
	'testvar'='here',
	'address'={
		'street'='123 Anywhere Lane',
		'city'='Grand Rapids',
		'state'='Michigan',
		'postalcode'='49546',
		'country'='USA'
	},
	'phone'={
		'home'='616-123-4567',
		'work'='616-321-7654',
		'mobile'='616-987-6543'
	}
	}).create();

Once we've created the document, it automatically becomes the Active Entity.

var isLoaded=person.loaded(); //will return true	

There is a special _id value that is created by MongoDB when the document is inserted. This serves as your "primary key" provides the unique identifier for the document (when you query for it directly, Mongo is really, really fast):

var pkey=person.get_id();

You may add human readable unique values (tags/slugs) and index them:

property name="tag" schema=true index=true unique=true;

Now let's reset our entity and re-find it. The where() method accepts either where('name','value') arguments or where('name','operator','value') 1:

person = person.reset().where('first_name','John').where('last_name','Doe').find();

Let's change our phone number:

person.set('phone.home','616-555-8789').update();

We can use our dot notation to find that record again

person = person.reset().where('phone.home','616-555-8789').find()

Now let's duplicate that document so we can play with multiple record sets

var newperson = structCopy(person.get_document());

structDelete(newperson,'_id');

newperson = this.reset().populate(newperson).set('first_name','Jane').set('last_name','Doe').create();

Now we can find our multiple records - which will return an array (Note: We probably don't need to use reset(), but it's a good practice to clear any active query criteria from previous queries)

var people = this.reset().findAll();	

for(var peep in people){
	writeOutput("#peep.first_name# #peep.last_name# is in the house!");
}

Here's where we diverge from RDBMS: MongoDB uses a "cursor" on multiple record sets. It is extremely fast (with some limitations) and, if you're going be looping through a large number of documents, is the way to go. Because of the way the cursor is designed, it doesn't actually start executing queries on the database until the first time a record is requested. If we use the "asCursor" argument in findAll(boolean asCursor=false,boolean asJSON=false), we recevie the cursor back:

var people = this.reset().findAll(true);  //or findAll(asCursor=true), if you're feeling verbose	

while(people.hasNext()){
	var peep=people.next();
	writeOutput('#peep.first_name# #peep.last_name# is in the house!');
}

Lastly, let's clean up our test documents. The delete() function allows a boolean argument of "truncate" which defaults to FALSE. If you set this argument to true, without a loaded record or existing criteria, it will delete all documents from the collection. In this case, we're just going to delete our records one at a time, using our cursor:

var people = this.reset().findAll(true);

while(people.hasNext()){
	var peep=people.next();
	//notice how we're using bracket notation for our _id value. This is necessary because calling peep._id on the cursor object will throw an error  
	this.get(peep['_id']).delete();
}
	

Optionally, you could delete all records matching a given criteria using a where() clause:

var noDoes = this.reset().where('last_name','Doe').delete();

That's basic CRUD functionality. Read the API documentation for details on the individual functions and arguments.


1 Valid operators currently include "=","!=","<",">",">=","<=","IN" and "Exists"

Clone this wiki locally