Migrating IndexDefinition DSL syntax
In Ucommerce 9.4 we introduce a new DSL (domain specific language). With this, you are now able to chain methods on each field individually. This means that specifying each field’s options has been made simpler. An example could be making one field into a facet, and later adding ranges to said facet. With each individual field having it’s own chain of methods, the definition is now also easier to read and understand.
Below you will find the exact steps you need to take to upgrade your code for version 9.4. If this is the first time reading the article, please take a moment and also read the overview to get a deeper understanding and to find out if any of the indexing improvements could be useful to you.
Before:
indexDefinition.IdField(p => p.Guid.ToString()) .PricesField(p => p.UnitPrices) .Field(p => p.LongDescription, IndexOptions.FullText) .Field(p => p["DynamicColor"], typeof(string)) .Field(p => p["DynamicShowOnHomePage"]) .Field("Price", typeof(double)) .Facet(p => p.Color, new FacetOptions { Ranges = new List<Range> { new Range("(0-49)"), new Range { Label = "1000.6 - 10000", From = 1000.6, To = 10000 }, new Range { Label = "10001 - 100000", From = 10001, To = 100000 } } })
After:
var indexDefinition = Ucommerce.Infrastructure.ObjectFactory.Instance.Resolve<IndexDefinition<Ucommerce.Search.Models.Product>>(); indexDefinition.IdField(p => p.Guid.ToString()); indexDefinition.Field(p => p.UnitPrices); indexDefinition.Field(p => p.LongDescription) .FullText(); indexDefinition.Field(p => p["DynamicColor"], typeof(string)); indexDefinition.Field(p => p["DynamicShowOnHomePage"]); indexDefinition.Field("Price", typeof(double)); indexDefinition.Field(p => p.UnitPrices) .Facet() .Range("0-49") .Range("1000.6 - 10000)") .Range("10001 - 100000");
Overview:
Display Names
You can set a per-culture display name for each field. The values are stored on the FieldDefinition
as a Dictionary<string, string>
where the key is the culture code, and the value is the display name provided.
this.Field(p => p.Name) .DisplayName("en-US", "Shoe") .DisplayName("da-DK", "Sko") .DisplayName("de-DE", "Schuh");
To retrieve the value, you can access it via the queried Index:
var index = Ucommerce.Infrastructure.ObjectFactory.Instance.Resolve<IIndex<Product>>(); index.Definition.FieldDefinitions["Color"].GetDisplayName("en-US");
For facets, the display name is returned via the Facet model for convenience:
var result = index.Find(new CultureInfo("en-US")).ToFacets(); var displayName = result.Facets.Single(x => x.Name == "Color").DisplayName;
A default fallback can be provided by not specifying a culture code.
this.Field(p => p.Name) .DisplayName("en-US", "Shoe") .DisplayName("da-DK", "Sko") .DisplayName("de-DE", "Schuh") .DisplayName("Shoe");
In case a default fallback has not been provided, the fallback will use the name of the field.
Chaining
With the new DSL syntax, you will now be chaining from IndexDefinition to Field, to Facet, respectively, as opposed to the old syntax, where every method would return an IndexDefinition.
Example with the new syntax:
indexDefinition.Field(p => p.Name).Facet();
IndexOptions
Regarding IndexOptions, the new syntax includes extension methods for these, as opposed to the old syntax in which you would pass the IndexOptions as a parameter when creating a field.
Example with the old syntax:
indexDefinition.Field(p => p.Name, IndexOptions.FullText);
Example with the new syntax:
indexDefinition.Field(p => p.Name).FullText();
Suggestable fields
The extension methods mentioned above, also changes the way a “Suggestable field” is created. examples can be seen below:
Using the old syntax:
indexDefinition.Suggestable(p => p.Name);
Using the new syntax:
indexDefinition.Field(p => p.Name).Suggestable();
Ranges
The new DSL syntax also includes a different way of creating Ranges for facets. This method only requires the Range “label”, and has no need for a “from” and “to” parameter, examples below:
Using the old syntax:
indexDefinition.Facet(p => p.UnitPrices, new FacetOptions { Ranges = new List<Range> { new Range("(0-49)"), new Range { Label = "1000.6 - 10000", From = 1000.6, To = 10000 }, new Range { Label = "10001 - 100000", From = 10001, To = 100000 } } });
Using the new syntax:
indexDefinition.Field(p => p.UnitPrices) .Facet() .Range("(0-49)") .Range("1000.6 - 10000") .Range("10001 - 100000");
As seen in the example of the old syntax above, we used to have a class called FacetOptions. In the new syntax, and IndexDefinition design, this class is no longer used, and all the “options” for facets, are now saved on the FacetDefinition itself.
Field type
In regard to field type, no changes has been made - and therefore these are still passed as a parameter when specifying a field. Example below.
Using the new syntax:
indexDefinition.Field(p => p.Name, typeof(string));