Override Field Values during Indexing
Sometimes you need more control over how field values are indexed to the search engine. It might be converting from one type to another, say from a string to int, or to provide a list of values for one field in cases where multiple values are stored for one field.
To achieve that you can register a number of IPropertyValueConveters, each responsible for dealing with a single or multiple fields and ultimately how are stored in the search engine.
Please note that this capability was introduced in version 5.3.0.14057.
IPropertyValueConverter
The interface uses the Supports
methods to determine whether a given value converter is applicaple to the IProperty
in question. If none is found the DefaultPropertyValueConverter
will be used basically passing through the existing value without modifying it.
/// <summary> /// Converts value of an <see cref="IProperty"/> to other values. /// </summary> public interface IPropertyValueConverter { /// <summary> /// Can this converter work with the property in question. /// </summary> /// <param name="property"></param> /// <returns></returns> bool Supports(IProperty property); /// <summary> /// Convert to new value. /// </summary> /// <param name="property"></param> /// <returns></returns> object Convert(IProperty property); }
Overriding a Property Value
In some cases you might need to override the value produced to supply a more appropriate type or a completely different value. The Ucommerce search engine supports multi-valued fields out of the box, but needs information about handling the existing values from the product database. Specifially CMS property editors tend to deal with multi values in wildly different ways so each might require special handling.
The example here will be a field with values split by the char ",". For the search engine to pick individual values it has to be converted to an IEnumerable
type like a List
type.
Here's what that would look like:
/// <summary> /// Splits the string on "," and returns a /// value for each of the substrings split /// from the original. /// </summary> /// <param name="property"></param> /// <returns></returns> public object Convert(IProperty property) { object val = property.GetValue(); if (val == null) return null; return val.ToString() .Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries); }
And finally we need to qualify the field as to avoid using this value converter for every field:
/// <summary> /// Supports the field if the configured fieldName /// is the same as the one on the property. /// </summary> /// <param name="property"></param> /// <returns></returns> public bool Supports(IProperty property) { return property.GetDefinitionField().Name == "MyMultiValuedField"; }
Using the Built-in MultiValuedFieldConverter
Turns out multi valued fields are quite common and so Ucommerce comes with the MultiValuedPropertyValueConverter
out of the box, which can be configured to target any field using the technique outlined above.
All you need to do to enable it is add a new configuration file called Search.config to Ucommerce/Apps/MyApp
and set up the name of the field you want to split and the char(s) you wish to split on and it will work like the above example.
<configuration> <components> <component id="MultiValuedPropertyValueConverter" service="UCommerce.Search.Indexers.IPropertyValueConverter, UCommerce" type="UCommerce.Search.Indexers.PropertyValueConverters.MultiValuedPropertyValueConverter, UCommerce"> <parameters> <fieldName>MyMultiValuedField</fieldName> <splitOn>,</splitOn> </parameters> </component> </components> </configuration>
You can set up multiple instances of MultiValuedPropertyValueConverter
with different config values, just keep in mind that each has to have its own unique Ids; otherwise the last instance will override other registrations.