Skip to content
This repository has been archived by the owner on Oct 8, 2020. It is now read-only.

Control what to index

Daniel Wertheim edited this page Nov 29, 2012 · 18 revisions

Indexing in SisoDb is the process of flattening the complete object graph and creating a key-value representation of it, for the purpose of querying. Even if you have nested complex types or nested arrays; all these values are stored in the indexes tables (more info) which only purpose is for executing queries against.

Everything is everything!

Everything that is meaningful to query is indexed in the object graph. This means that e.g byte arrays are not indexed.

Why would I tamper with the indexing?

To get better performance, by not inserting every key-value index used for querying, which would gain better insert performance, but also to not store unnecessary data that you NEVER WILL QUERY ON.

But what happens if I do want them queryable at a later time?

The actual data representing your object graph is not stored in the indexes-tables, but in the structure table. You can therefore "reindex" the structures by re-saving them, e.g using Db.Maintenance.RegenerateQueryIndexesFor. Read more under Maintenance.

How-to control what to index

There are two alternatives, and personally I like the "Alternative approach" explained below. But first, lets look at another option.

Manual adjustments of the indexing process

You can register specific structure type configurations by calling either of the following:

  • Db.Configure().StructureType(typeof(Customer), cfg => ...);
  • Db.Configure().StructureType<Customer>(cfg => ...);

Using the cfg, you have the following options:

  • AllowNestedStructures()
  • DoNotIndexThis("Firstname", "Address")
  • DoNotIndexThis(x => x.Firstname, x => x.Address)
  • OnlyIndexThis("Lastname", "ZipCode")
  • OnlyIndexThis(x => x.Lastname, x => x.ZipCode)

Last in wins! Hence if you call DoNotIndex("Address.Street") and then calls OnlyIndexThis("LastName") only LastName will be indexed, since any DoNotIndex registrations will get cleared. The inverse behavior exists as well.

Examples

Lets have a look at the model for these examples.

public class Root
{
    public Guid StructureId { get; set; }
    public int Int1 { get; set; }
    public string String1 { get; set; }
    public Nested Nested { get; set; }
}

public class Nested
{
    public int Int1 { get; set; }
    public string String1 { get; set; }
}

Example - DoNotIndexThis

Let's say I don't want to index any of the nested values as well as the String1 values of the Root.

Db.Configure().StructureType<Root>(
    cfg => cfg.DoNotIndexThis(r => r.String1, r => r.Nested));

or

Db.Configure().StructureType(
    typeof(Root), 
    cfg => cfg.DoNotIndexThis("String1", "Nested"));

Pay attention to that I don't specify Nested.Int1 and Nested.String1 since I exclude their container Nested, nothing on Nested will be indexed. You can of course select specific field(s) under nested items.

Db.Configure().StructureType<Root>(
    cfg => cfg.DoNotIndexThis(r => r.String1, r => r.Nested.String1));

or

Db.Configure().StructureType(
    typeof(Root), 
    cfg => cfg.DoNotIndexThis("String1", "Nested.String1"));

Example - OnlyIndexThis

Let's say you only want to index a few members, e.g I only want to index the Nested.Int1 values.

Db.Configure().StructureType<Root>(
    cfg => cfg.OnlyIndexThis(r => Nested, r => r.Nested.Int1));

or

Db.Configure().StructureType(
    typeof(Root), 
    cfg => cfg.OnlyIndexThis("Nested", "Nested.Int1"));

Pay attention to that I specify Nested and Nested.Int1. If I don't specify Nested, then it's members will not be traversed.

Alternative approach

You can also make use of an interface or a base-class that defines the "contract" of the structure in terms of what you want to make queryable. The actual instance-type though is what ends up in the JSON structure.

This is the alternative I would use. Why? Because when I look at my model (classes, interfaces) I immediately can see what's going to be indexed.

public class Customer : ICustomer
{
    public Guid Id { get; set;}
    public string CustomerNo { get; set; }
    public string Name { get; set; }
    public Address DeliveryAddress { get; set; }
    ...
    ...
}

public interface ICustomer
{
    string CustomerNo {get;set;}
    string Name {get;set;}
}

db.UseOnceTo().Insert<ICustomer>(customer);

This example will create two queryable indexes CustomerNo and Name, but the JSON structure will contain all the members of the Customer-class.