-
Notifications
You must be signed in to change notification settings - Fork 25
Control what to index
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 that is meaningful to query is indexed in the object graph. This means that e.g byte arrays are not indexed.
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.
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.
There are two alternatives, and personally I like the "Alternative approach" explained below. But first, lets look at another option.
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.
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; }
}
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"));
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.
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.