Skip to content
jlarsson edited this page Sep 12, 2011 · 9 revisions

Introduction

Indices in KiwiDB are designed to flexible and easy to use in real world scenarios without big surprises.

Dude, this looks familiar...

KIWIDB HAS STOLEN THE WHOLE CONCEPT OF INDICES FROM MONGODB.

So, I said it. And perhaps it will also give you a sense of familiarity.

But beware. MongoDB is quite smart since it can use all sort of predicate (less than, bigger than etc), whereas KiwiDB only understands one:

  • equality of values

Luckily, as we will see, the meaning of equality can be configured...

Some definitions

Lets say you have an object model like this:

public class User {
	public string Name {get; set;}
	public Ticket[] Tickets {get; set;}
]
public class Ticket{
	bool IsOpen{ get; set; }
	string Category {get; set; }
	string Text {get; set; }
}

The operation of finding all users with open tickets can be written like

var collection = new Collection("tickets.db")
var filter = new {Tickets = new {IsOpen = true}};
var usersWithOpenTickets = collection.Find<User>(filter);

Pay attention to the filter object. It encapsulates exactly the parts of User that we are interested in. In fact, Find() matches objects using at least equal to.

We can speed up the operation by creating an index.

var collection = new Collection("tickets.db")
collection.Indices.EnsureIndex("Tickets.IsOpen")

The index name "Tickets.IsOpen" is the JPath (Javascript object member path) to the member to index.

We dont have to specify any datatypes, since an index in practice happily indexes whatever you give it.

Unique indexing

Its possible to create a unique index to enforce that not more than one object may have that particular value.

collection.Indices.EnsureIndex(<Path to member>, new IndexOptions(){ IsUnique = true });

Inserting an object violating the uniqueness of the index will throw a DuplicateKeyException.

Case insensitive indexing

In the case an indexed value is a string, it can be handled inoring case.

collection.Indices.EnsureIndex(<Path to member>, new IndexOptions(){ WhenStringThenIgnoreCase = true });

Special date index

Normally, dates are compared using the full (year,month,day,hour,second,millisecond) value, but in the case when only the day matters, use

collection.Indices.EnsureIndex(<Path to member>, new IndexOptions(){ WhenDateThenIgnoreTimeOfDay = true });

Indexed data types

After serializing an object to Json, the index values are extacted and depending on type they are handled differently:

Simple types

Simple types ar indexed by exact value. The simple types are those directly convertible to

  • booleans (System.Boolean)
  • integers (System.Int32),
  • strings (System.String)
  • dates (System.DateTime)
  • floating point numbers (System.Double)

List types

Arrays, lists or other enumerables are indexed by indexing each separate member.

Complex types

Complex types are not indexed, even though objects are perfectly valid Json values.

Null value indexing

Null values are indexed so you can search for them.

var collection = new Collection("tickets.db")
collection.Find(new {Tickets = null});

When should I call EnsureIndex?

Preferably at application startup. EnsureIndex will do nothing if an index with the same name and options exists, but its still not a completely free operation.

When will EnsureIndex fail?

EnsureIndex fails with a DuplicateKeyException if you upgrade and index to unique and values are not distinct.

EnsureIndex is currently slightly bugged, since it can't detect a change of index semantics, and thus might leave an old, bad index intact as long as the names match.

Can indices be dropped?

Yup, use DropIndex.

collection.Indices.DropIndex("Tickets.IsOpen")