Add custom data to index
In 9.4, we introduced the interface Ucommerce.Search.IAdorn that will allow you to add custom data to your index.
If your custom data is already in a definition field, this article is not for you. Please just add that property to your custom index definition.
One thing to mention, you can not store nested data structures. For example, you can not store a List of product relations, each with its own List of products.
Below is the interface. It has 2 methods for adding data to the index. One is for generic product properties, the second is used for language specific properties.
Ucommerce.Search.IAdorn`1
Description
When indexing Ts, provides a hook to transform, filter or amend the items going into the index. The Ts passed to Adorn have been localized, so any adornments must take this into account, adding data localized for each CultureInfo.
Methods
Adorn
-
Arguments
IEnumerable<Ucommerce.Search.T>
items
- Return type
Void
Adorn
-
Arguments
IEnumerable<Ucommerce.Search.T>
localizedItemsCultureInfo
culture
- Return type
Void
As one of the most requested usages of the index, I will add product relations to the product index. By default, the index has a list of all related products but that list does not take into consideration the type of relationship.
Below we will index product relationships and their types. Since the index will only allow storing of simple values, we index each relation by its type and save the GUID for the product rather than the product itself. That keeps the index size down while allowing us to query for the product.
Here is a code example:
using System.Collections.Generic; using System.Globalization; using System.Linq; namespace UcommerceCodeSamples.IndexAndSearch { public class AddingCustomIndex { public class ProductRelationsAdorner : Ucommerce.Search.IAdorn<Ucommerce.Search.Models.Product> { // Getting a product relation repository [Ucommerce.Infrastructure.Components.Windsor.Mandatory] private Ucommerce.EntitiesV2.IRepository<Ucommerce.EntitiesV2.ProductRelation> ProductRelationRepository { get; set; } public void Adorn(IEnumerable<Ucommerce.Search.Models.Product> products) { foreach (Ucommerce.Search.Models.Product product in products) { //collecting all the related products var relatedProducts = ProductRelationRepository.Select().Where(x => product.RelatedProducts.Contains(x.RelatedProduct.Guid ) && x.Product.Guid == product.Guid); //grouping them by type var relatedProductsGroupedByName = relatedProducts.ToLookup(x => x.ProductRelationType.Name, x => x.RelatedProduct.Guid); //adding the data to our index model. At this point the model has the data, but you still need to map it to your index. foreach (var productRelationType in relatedProductsGroupedByName) { product[productRelationType.Key] = productRelationType.ToList(); } } } public void Adorn(IEnumerable<Ucommerce.Search.Models.Product> localizedProducts, CultureInfo culture) { } } } }
Below is how you register the component. Read more about registering components here
<components> <component id="ProductRelationsAdorner" service="Ucommerce.Search.IAdorn`1[[Ucommerce.Search.Models.Product, Ucommerce.Search]], Ucommerce.Search" type="your_namespace.your_class, your_dll" /> </components>
And adding the field to the index definition:
this.Field(p => p["relation_name"]);
Please remember to restart of the website for the component to be registered and run the scratch indexer to populate the data of your index.