Indexing
Overview
Prerequisite
Fields have to be defined in Hawksearch in order for the data sent from Optimizely website to be saved in the Hawksearch indexes. For more details on field setup please refer to HawkSearch Field Setup.
Overall Approach
Passing data from an Optimizely solution (1 or multiple websites) to a Hawksearch engine (or more) has been designed as a 2-part process. Each part uses the Optimizely Scheduled Jobs support provided out of the box by the Optimizely framework:
- Full Indexing Job - process which extracts all cms (pages) & commerce (products/variants/bundles/packages) content from your Optimizely Solution, transforms each content into document objects which are then loaded into the Hawksearch Engine(s).
- Incremental Indexing Job - a process which uses Optimizely events raised when content is changed (published/deleted) in order to update the Hawksearch engine(s) with the latest version of data.
At the core of both indexing jobs sits a design based on a series of Handlers chained one after the other, each of them solving one particular indexing use case. This represents the first extensibility point of the indexing processes inside the connector. Additional handlers can be developed and chained as needed. For more details on how to do this, check How to Extend Handlers.
The more complex handlers (e.g. Product Indexing) are then built out of a series of Pipes which are usually extracting the content from the Optimizely databases, transforming them into Hawksearch document objects and then loading them into Hawksearch Engine(s) using the Hawksearch V4.0 API APIs. Additional pipes can be developed as needed. For more details on how to do this, check How to Extend Pipes.
Full Indexing Job
Steps (aka Handlers)
- Delete Previous (not set as current) Index
- Create Index
- Categories Indexing
- Rebuild Hierarchy
- Product Indexing
- Variants Indexing
- Bundles Indexing
- Packages Indexing
- CMS Content Indexing
- multiple pipelines can be added depending on the Optimizely page type required for indexing
- Rebuild All
- rebuilds autocomplete, percolator, learning search and related searches.
- Set new index as Current Index
Notes
- steps above are repeated for each engine (language) defined in the Configuring the Connector
- it is recommended to have this job running on a scheduled bases no more frequently that 1/day

Incremental Indexing Job
Steps (aka Handlers)
- Get Current Index
- Categories Incremental Indexing
- Categories Deletion
- Rebuild Hierarchy
- Cascading Events Handling
- Products Incremental Indexing
- Variants Incremental Indexing
- Bundles Incremental Indexing
- Packages Incremental Indexing
- Products / Variants / Bundles / Packages Deletion
- CMS Content Incremental Indexing
- CMS Content Deletion
- Rebuild All
Notes
- steps above are repeated for each engine (language) defined in the Configuring the Connector
- this job will not run if Full Indexing Job is already running
- it is recommended to have this job running on a scheduled bases with a frequency of 1 to 10 minutes
Events
- on publishing/expiring/deleting content the system will temporarily store information about content in a custom table
- a full list of events and how they are treated can be found here

Indexing Events
Tables below describe the types of actions/events which will require refreshing the documents stored in Hawksearch engines. Each event is added into a custom table (named hawk.IndexingQueue) when a particular action is taken (e.g. an editor publishes a new version of product, expires a variant, etc). Then, these events are picked up and resolved by the corresponding Handler inside the Incremental Indexing Job.
Commerce entities events & actions
Category Events
Category Event | Category | Product | Variant | Bundle | Package |
---|---|---|---|---|---|
publish category | index hierarchy | NA | NA | NA | NA |
Name in URL property changes on a category (1) | NA | index all products beneath category | index all variants beneath category | index all bundles beneath category | index all packages beneath category |
expire category | index hierarchy with IsActive false | NA | NA | NA | NA |
delete category | delete hierarchy | index all products beneath category | index all variants beneath category | index all bundles beneath category | index all packages beneath category |
move category (change parent category) (1,2) | index hierarchy | index all products beneath category | index all variants beneath category | index all bundles beneath category | index all packages beneath category |
link category to category (1) | index hierarchy | index all products beneath category | index all variants beneath category | index all bundles beneath category | index all packages beneath category |
Product Events
Product Event | Category | Product | Variant | Bundle | Package |
---|---|---|---|---|---|
publish product | NA | index product | index all variants | NA | NA |
expire product | NA | index product | index all variants | NA | NA |
delete product | NA | index product | index all variants | NA | NA |
add image to product (2) | NA | index product | index all variants | NA | NA |
delete image from product (2) | NA | index product | index all variants | NA | NA |
move product (change parent category) | NA | index product | index all variants | NA | NA |
link product to category | NA | index product | index all variants | NA | NA |
Variant Events
Variant Event | Category | Product | Variant | Bundle | Package |
---|---|---|---|---|---|
publish variant | NA | index product | index variant | index bundle | index package |
expire variant | NA | index product | index variant | index bundle | index package |
delete variant | NA | index product | index variant | index bundle | index package |
add image to variant (2) | NA | index product | index variant | index bundle | index package |
delete image from variant (2) | NA | index product | index variant | index bundle | index package |
move variant (change parent category) | NA | index product | index variant | index bundle | index package |
link variant to category | NA | index product | index variant | index bundle | index package |
link variant to product | NA | index product | index variant | NA | NA |
link variant to bundle | NA | index product | index variant | NA | NA |
link variant to kit/package | NA | NA | index variant | NA | index package |
Bundle Events
Bundle Event | Category | Product | Variant | Bundle | Package |
---|---|---|---|---|---|
publish bundle | NA | NA | index all variants | index bundle | NA |
expire bundle | NA | NA | index all variants | index bundle | NA |
delete bundle | NA | NA | index all variants | delete bundle | NA |
add image to bundle (2) | NA | NA | index all variants | index bundle | NA |
delete image from bundle (2) | NA | NA | index all variants | index bundle | NA |
move bundle (change parent category) | NA | NA | index all variants | index bundle | NA |
link bundle to category | NA | NA | index all variants | index bundle | NA |
Package Events
Package Event | Category | Product | Variant | Bundle | Package |
---|---|---|---|---|---|
publish package | NA | NA | index all variants | NA | index package |
expire package | NA | NA | index all variants | NA | index package |
delete package | NA | NA | index all variants | NA | index package |
add image to package (2) | NA | NA | index all variants | NA | index package |
delete image from package (2) | NA | NA | index all variants | NA | index package |
move package (change parent category)link package to category | NA | NA | index all variants | NA | index package |
Cms Entities Events and Actions
Optimizely Event | Optimizely-Hawksearch Connector Indexing Actions |
---|---|
publish page | index page and all subpages |
Name in URL' property changes on a page | index page and all subpages |
expire page | index page and all subpages |
delete page (move to wastebasket) (2) | index page and all subpages |
move page (2) | index page and all subpages |
restore page (restore from wastebasket) (2) | index page and all subpages |
(1) introduces a cascading event and a new handler
(2) solved via Optimizely Content API - MovedContent event
Index Setup
Overview
There are 3 main indexing strategies that the connector supports:
- Default. Variant Attributes Roll-up inside their parent product
- Index variants separately. Separate documents are created for products and variants
- Index Variants as child of parent.
To set up indexing inside your project, you should use the Initialization Modules capability (by implementing the IConfigurableModule
interface) provided by the Optimizely platform and make your module dependent on the BasicHawksearchInitialization
module which is part of the installed connector.
Configure Indexing Services
In the ConfigureContainer
method, register services needed to index different types of content. Available options are:
container.AddHawksearchCategoryIndexing<YOUR CLASS EXTENDING NodeContent>();
container.AddHawksearchProductIndexing<YOUR CLASS EXTENDING ProductContent>();
container.AddHawksearchVariantIndexing<YOUR CLASS EXTENDING VariationContent>();
container.AddHawksearchBundleIndexing<YOUR CLASS EXTENDING BundleContent>();
container.AddHawksearchPackageIndexing<YOUR CLASS EXTENDING PackageContent>();
container.AddHawksearchPageIndexing<YOUR CLASS EXTENDING PageData>()
AddHawksearchPageIndexing
extension method can be used multiple times with different generics in order to have multiple cms page types indexed in Hawksearch.
If you don’t intend to index some of the cms or commerce entity type, there’s no need to register those services (e.g. if you don’t have bundles or packages in your project, you should not call the AddHawksearchBundleIndexing
or the AddHawksearchPackageIndexing
methods).
Initialize Indexing Chains
In the Initialize
method, register the 2 chains of Handlers needed for the Full & Incremental Indexing jobs as follows:
public void Initialize(InitializationEngine context)
{
Container.Service.Configure(config =>
{
config.For<IFullIndexingChain>().Add(() => FullIndexingChain(Container.Service))
.Transient();
config.For<IIncrementalIndexingChain>().Add(() => IncrementalIndexingChain(Container.Service))
.Transient();
});
}
private IndexingChain FullIndexingChain(IContainer container)
{
return new IndexingChain(container)
.AddHandler<DeletePreviousIndexHandler>()
.AddHandler<CreateIndexHandler>()
.AddHandler<CategoriesIndexingHandler<YOUR CLASS EXTENDING NodeContent>>()
.AddHandler<HierarchyRebuildHandler>()
.AddHandler<ProductsIndexingHandler<YOUR CLASS EXTENDING ProductContent>>()
.AddHandler<VariantsIndexingHandler<YOUR CLASS EXTENDING VariationContent>>()
.AddHandler<BundlesIndexingHandler<YOUR CLASS EXTENDING BundleContent>>()
.AddHandler<PackagesIndexingHandler<YOUR CLASS EXTENDING PackageContent>>()
.AddHandler<PagesIndexingHandler<YOUR CLASS EXTENDING PageData>>()
... other PagesIndexingHandler registrations for different types of cms pages
.AddHandler<RebuildIndexHandler>()
.AddHandler<SetCurrentIndexHandler>();
}
private IndexingChain IncrementalIndexingChain(IContainer container)
{
return new IndexingChain(container)
.AddHandler<GetCurrentIndexHandler>()
.AddHandler<CategoriesIncrementalIndexingHandler<YOUR CLASS EXTENDING NodeContent>>()
.AddHandler<CategoriesDeletionHandler>()
.AddHandler<HierarchyRebuildHandler>()
.AddHandler<CategoriesCascadeIndexingHandler>()
.AddHandler<ProductsIncrementalIndexingHandler<YOUR CLASS EXTENDING ProductContent>>()
.AddHandler<VariantsIncrementalIndexingHandler<YOUR CLASS EXTENDING VariationContent>>()
.AddHandler<BundlesIncrementalIndexingHandler<YOUR CLASS EXTENDING BundleContent>>()
.AddHandler<PackagesIncrementalIndexingHandler<YOUR CLASS EXTENDING PackageContent>>()
.AddHandler<PagesIncrementalIndexingHandler<YOUR CLASS EXTENDING PageData>>()
... other PagesIncrementalIndexingHandler registrations for different types of cms pages
.AddHandler<EntriesDeletionHandler>()
.AddHandler<PagesDeletionHandler>()
.AddHandler<RebuildIndexHandler>();
}
If you don’t intend to index some of the cms or commerce entity type, you should not add that particular handlers to your indexing chains (e.g. if you don’t have bundles, you will skip adding the BundlesIndexingHandler
and the BundlesIncrementalIndexingHandler
to the indexing chains).
If you don’t intend to index cms pages, PagesIndexingHandler
,PagesIncrementalIndexingHandler
,PagesDeletionHandler
should not be added to the indexing chains.
[IncludeInHawksearch] Attribute
[IncludeInHawksearch
] is an attribute used to decorate properties which we want to index.
Examples:
[IncludeInHawksearch]
[BackingType(typeof(PropertyString))]
[Display(Name = "Brand", GroupName = SystemTabNames.Content, Order = 15)]
public virtual string Brand { get; set; }
[IncludeInHawksearch]
[Display(Name = "On sale", GroupName = SystemTabNames.Content, Order = 50)]
public virtual bool OnSale { get; set; }
This attribute is common for all 3 indexing strategies. For the Variant Attributes Roll-up Strategy, the properties of the variant decorated with this attribute will be rolled-up inside the parent product.
Out of the box, only properties with the following types can be decorated with [IncludeInHawksearch
] attribute:
.NET specific
string
int
double
decimal
bool
DateTime
Optimizely specific
ContentReference
XhtmlString
Other property types will throw a NotSupportedException
.
To support more types, please refer to this.
Variant Attributes Roll-up Strategy
This strategy relies on the fact that no variants will be indexed as documents inside Hawksearch. It is the default strategy of the conntector.
Variant properties, decorated with [IncludeInHawksearch
] attribute, will be rolled-up inside the parent product. The product document indexed will contain information coming from both the product itself and it’s variants.
To use this indexing strategy, set variantindexingstrategy to “VariantAttributesRollUp“ in Web.config, or do not include variantindexingstrategy at all.
<hawksearch ...
variantindexingstrategy="VariantAttributesRollUp"
</hawksearch>
Example
[IncludeInHawksearch]
public virtual string Color { get; set; }
The “Color” property will be rolled-up from the variant to the product. The “Color” field on a product in Hawksearch will contain a list of available colors, each one of them extracted from a variant.
Considerations
- ariant Indexing is unavailable under this strategy.
AddHawksearchVariantIndexing
will throw aNotSupportedException
if attempted to be used inside chain initialization. Also,VariantsIndexingHandler
andVariantsIncrementalIndexingHandler
pipes will be rendered useless and throw exceptions. - Price and inventory indexing options from Web.config will have no effect, because Variant Indexing is unavailable.
Indexing Setup Example: Optimizely Foundation
A full version of the HawksearchInitialization
class used to set up indexing on the Optimizely Foundation solution can be found below:
using EPiServer.Commerce.Catalog.ContentTypes;
using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using EPiServer.ServiceLocation;
using Foundation.Features.CatalogContent.Bundle;
using Foundation.Features.CatalogContent.Package;
using Foundation.Features.CatalogContent.Product;
using Foundation.Features.CatalogContent.Variation;
using Foundation.Features.Hawksearch.Indexing.Pipes;
using Foundation.Features.Hawksearch.Indexing.Pipes.Pages;
using Foundation.Features.Locations.LocationItemPage;
using Optimizely.Hawksearch.Connector.Contracts;
using Optimizely.Hawksearch.Connector.Core;
using Optimizely.Hawksearch.Connector.Handlers;
using Optimizely.Hawksearch.Connector.Handlers.Category;
using Optimizely.Hawksearch.Connector.Handlers.Page;
using Optimizely.Hawksearch.Connector.Handlers.Product;
using Optimizely.Hawksearch.Connector.Initialization;
using StructureMap;
namespace Foundation.Features.Hawksearch.Indexing
{
[InitializableModule]
[ModuleDependency(typeof(BasicHawksearchInitialization))]
public class HawksearchInitialization : IConfigurableModule
{
internal Injected<IContainer> Container;
public void ConfigureContainer(ServiceConfigurationContext context)
{
var container = context.StructureMap();
container.AddHawksearchCategoryIndexing<NodeContent>();
container.AddHawksearchProductIndexing<GenericProduct, GenericVariant>()
.ExtendProductIndexing<GenericProduct, EntriesImagePipe<GenericProduct>>()
.ExtendProductIndexing<GenericProduct, GenericProductAttributesPipe>();
container.AddHawksearchBundleIndexing<GenericBundle, GenericVariant>();
container.AddHawksearchPackageIndexing<GenericPackage, GenericVariant>();
container.AddHawksearchPageIndexing<LocationItemPage>()
.ExtendPageIndexing<LocationItemPage, FoundationPageAttributesPipe<LocationItemPage>>()
.ExtendPageIndexing<LocationItemPage, LocationItemPageAttributesPipe>();
container.AddHawksearchPageIndexing<StandardPage.StandardPage>()
.ExtendPageIndexing<StandardPage.StandardPage, FoundationPageAttributesPipe<StandardPage.StandardPage>>()
.ExtendPageIndexing<StandardPage.StandardPage, StandardPageAttributesPipe>();
}
public void Initialize(InitializationEngine context)
{
Container.Service.Configure(config =>
{
config.For<IFullIndexingChain>().Add(() => FullIndexingChain(Container.Service))
.Transient();
config.For<IIncrementalIndexingChain>().Add(() => IncrementalIndexingChain(Container.Service))
.Transient();
});
}
private IndexingChain FullIndexingChain(IContainer container)
{
return new IndexingChain(container)
.AddHandler<DeletePreviousIndexHandler>()
.AddHandler<CreateIndexHandler>()
.AddHandler<CategoriesIndexingHandler<NodeContent>>()
.AddHandler<HierarchyRebuildHandler>()
.AddHandler<ProductsIndexingHandler<GenericProduct>>()
.AddHandler<BundlesIndexingHandler<GenericBundle>>()
.AddHandler<PackagesIndexingHandler<GenericPackage>>()
.AddHandler<PagesIndexingHandler<LocationItemPage>>()
.AddHandler<PagesIndexingHandler<StandardPage.StandardPage>>()
.AddHandler<RebuildIndexHandler>()
.AddHandler<SetCurrentIndexHandler>();
}
private IndexingChain IncrementalIndexingChain(IContainer container)
{
return new IndexingChain(container)
.AddHandler<GetCurrentIndexHandler>()
.AddHandler<CategoriesIncrementalIndexingHandler<NodeContent>>()
.AddHandler<CategoriesDeletionHandler>()
.AddHandler<HierarchyRebuildHandler>()
.AddHandler<CategoriesCascadeIndexingHandler>()
.AddHandler<ProductsIncrementalIndexingHandler<GenericProduct>>()
.AddHandler<BundlesIncrementalIndexingHandler<GenericBundle>>()
.AddHandler<PackagesIncrementalIndexingHandler<GenericPackage>>()
.AddHandler<PagesIncrementalIndexingHandler<LocationItemPage>>()
.AddHandler<PagesIncrementalIndexingHandler<StandardPage.StandardPage>>()
.AddHandler<EntriesDeletionHandler>()
.AddHandler<PagesDeletionHandler>()
.AddHandler<RebuildIndexHandler>();
}
public void Uninitialize(InitializationEngine context)
{
}
}
}
Variant as Separate Document Strategy
This strategy relies on the fact that products and variants are indexed as separate documents inside Hawksearch. Their relationships are not expressed - it is not known which variants belong to which products in a parent-child fashion. The properties decorated with [IncludeInHawksearch
] attribute will be the ones that are indexed for each variant.
To use this indexing strategy, set variantindexingstrategy to “SeparateDocuments“ in Web.config.
<hawksearch ...
variantindexingstrategy="SeparateDocuments"
</hawksearch>
This should be the go-to strategy for variant-only catalogs.
For this strategy, it is important to add the Variant handlers and Variant Indexing extension method(s) in the initialization module:
container.AddHawksearchVariantIndexing<GenericVariant>()
.ExtendVariantIndexing<GenericVariant, EntriesImagePipe<GenericVariant>>()
.ExtendVariantIndexing<GenericVariant, GenericVariantAttributesPipe>()
.ExtendVariantIndexing<GenericVariant, GenericVariantShippingPipe>();
private IndexingChain FullIndexingChain(IContainer container)
{
return new IndexingChain(container)
.AddHandler<DeletePreviousIndexHandler>()
...
.AddHandler<VariantsIndexingHandler<GenericVariant>>()
...
;
}
private IncrementalIndexingChain FullIndexingChain(IContainer container)
{
return new IndexingChain(container)
.AddHandler<DeletePreviousIndexHandler>()
...
.AddHandler<VariantsIncrementalIndexingHandler<GenericVariant>>()
...
;
}
Indexing Setup Example: Optimizely Foundation
A full version of the HawksearchInitialization
class used to set up indexing on the Optimizely Foundation solution can be found below:
using EPiServer.Commerce.Catalog.ContentTypes;
using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using EPiServer.ServiceLocation;
using Foundation.Features.CatalogContent.Bundle;
using Foundation.Features.CatalogContent.Package;
using Foundation.Features.CatalogContent.Product;
using Foundation.Features.CatalogContent.Variation;
using Foundation.Features.Hawksearch.Indexing.Pipes;
using Foundation.Features.Hawksearch.Indexing.Pipes.Pages;
using Foundation.Features.Locations.LocationItemPage;
using Optimizely.Hawksearch.Connector.Contracts;
using Optimizely.Hawksearch.Connector.Core;
using Optimizely.Hawksearch.Connector.Handlers;
using Optimizely.Hawksearch.Connector.Handlers.Category;
using Optimizely.Hawksearch.Connector.Handlers.Page;
using Optimizely.Hawksearch.Connector.Handlers.Product;
using Optimizely.Hawksearch.Connector.Initialization;
using StructureMap;
namespace Foundation.Features.Hawksearch.Indexing
{
[InitializableModule]
[ModuleDependency(typeof(BasicHawksearchInitialization))]
public class HawksearchInitialization : IConfigurableModule
{
internal Injected<IContainer> Container;
public void ConfigureContainer(ServiceConfigurationContext context)
{
var container = context.StructureMap();
container.AddHawksearchCategoryIndexing<NodeContent>();
container.AddHawksearchProductIndexing<GenericProduct, GenericVariant>()
.ExtendProductIndexing<GenericProduct, EntriesImagePipe<GenericProduct>>()
.ExtendProductIndexing<GenericProduct, GenericProductAttributesPipe>();
container.AddHawksearchVariantIndexing<GenericVariant>()
.ExtendVariantIndexing<GenericVariant, EntriesImagePipe<GenericVariant>>()
.ExtendVariantIndexing<GenericVariant, GenericVariantAttributesPipe>()
.ExtendVariantIndexing<GenericVariant, GenericVariantShippingPipe>();
container.AddHawksearchBundleIndexing<GenericBundle, GenericVariant>();
container.AddHawksearchPackageIndexing<GenericPackage, GenericVariant>();
container.AddHawksearchPageIndexing<LocationItemPage>()
.ExtendPageIndexing<LocationItemPage, FoundationPageAttributesPipe<LocationItemPage>>()
.ExtendPageIndexing<LocationItemPage, LocationItemPageAttributesPipe>();
container.AddHawksearchPageIndexing<StandardPage.StandardPage>()
.ExtendPageIndexing<StandardPage.StandardPage, FoundationPageAttributesPipe<StandardPage.StandardPage>>()
.ExtendPageIndexing<StandardPage.StandardPage, StandardPageAttributesPipe>();
}
public void Initialize(InitializationEngine context)
{
Container.Service.Configure(config =>
{
config.For<IFullIndexingChain>().Add(() => FullIndexingChain(Container.Service))
.Transient();
config.For<IIncrementalIndexingChain>().Add(() => IncrementalIndexingChain(Container.Service))
.Transient();
});
}
private IndexingChain FullIndexingChain(IContainer container)
{
return new IndexingChain(container)
.AddHandler<DeletePreviousIndexHandler>()
.AddHandler<CreateIndexHandler>()
.AddHandler<CategoriesIndexingHandler<NodeContent>>()
.AddHandler<HierarchyRebuildHandler>()
.AddHandler<ProductsIndexingHandler<GenericProduct>>()
.AddHandler<VariantsIndexingHandler<GenericVariant>>()
.AddHandler<BundlesIndexingHandler<GenericBundle>>()
.AddHandler<PackagesIndexingHandler<GenericPackage>>()
.AddHandler<PagesIndexingHandler<LocationItemPage>>()
.AddHandler<PagesIndexingHandler<StandardPage.StandardPage>>()
.AddHandler<RebuildIndexHandler>()
.AddHandler<SetCurrentIndexHandler>();
}
private IndexingChain IncrementalIndexingChain(IContainer container)
{
return new IndexingChain(container)
.AddHandler<GetCurrentIndexHandler>()
.AddHandler<CategoriesIncrementalIndexingHandler<NodeContent>>()
.AddHandler<CategoriesDeletionHandler>()
.AddHandler<HierarchyRebuildHandler>()
.AddHandler<CategoriesCascadeIndexingHandler>()
.AddHandler<ProductsIncrementalIndexingHandler<GenericProduct>>()
.AddHandler<VariantsIncrementalIndexingHandler<GenericVariant>>()
.AddHandler<BundlesIncrementalIndexingHandler<GenericBundle>>()
.AddHandler<PackagesIncrementalIndexingHandler<GenericPackage>>()
.AddHandler<PagesIncrementalIndexingHandler<LocationItemPage>>()
.AddHandler<PagesIncrementalIndexingHandler<StandardPage.StandardPage>>()
.AddHandler<EntriesDeletionHandler>()
.AddHandler<PagesDeletionHandler>()
.AddHandler<RebuildIndexHandler>();
}
public void Uninitialize(InitializationEngine context)
{
}
}
}
Variant as Child of Parent Strategy
This strategy relies on the fact that variants will be indexed as children for their parent product/bundle/package using the hawk_child_attributes JSON property.
The properties decorated with [IncludeInHawksearch] attribute will be the ones that are indexed for each variant residing below hawk_child_attributes. The product itself is, of course, indexed.
To use this indexing strategy, set variantindexingstrategy to “VariantAsChildOfParent“ in Web.config.
<hawksearch ...
variantindexingstrategy="VariantAsChildOfParent"
</hawksearch>
Example
[IncludeInHawksearch]
public virtual string Color { get; set; }
The “Color” property will be included in the variant indexed under hawk_child_attributes.
Convention
Every field that will be equivalent to a variant property shall be prefixed by “Child_” in Hawksearch. Also, it will have the “Is Child Field?” flag set to “ON”
Example:
- For ->
[IncludeInHawksearch]
public virtual string Color { get; set; }
we have Child_Color
- For ->
[IncludeInHawksearch]c
public virtual string Size { get; set; }
we have Child_Size
Default Fields
These fields are always included in indexing (can be found here)
Child_DisplayName
Child_Code
Child_Url
Considerations
- Variant Indexing is unavailable under this strategy.
AddHawksearchVariantIndexing
will throw aNotSupportedException
if attempted to be used inside chain initialization. Also,VariantsIndexingHandler
andVariantsIncrementalIndexingHandler
pipes will be rendered useless and throw exceptions. - Price and inventory indexing options from Web.config will have no effect, because Variant Indexing is unavailable.
Indexing Setup Example: Optimizely Foundation
A full version of the HawksearchInitialization
class used to set up indexing on the Optimizely Foundation solution can be found below:
using EPiServer.Commerce.Catalog.ContentTypes;
using EPiServer.Framework;
using EPiServer.Framework.Initialization;
using EPiServer.ServiceLocation;
using Foundation.Features.CatalogContent.Bundle;
using Foundation.Features.CatalogContent.Package;
using Foundation.Features.CatalogContent.Product;
using Foundation.Features.CatalogContent.Variation;
using Foundation.Features.Hawksearch.Indexing.Pipes;
using Foundation.Features.Hawksearch.Indexing.Pipes.Pages;
using Foundation.Features.Locations.LocationItemPage;
using Optimizely.Hawksearch.Connector.Contracts;
using Optimizely.Hawksearch.Connector.Core;
using Optimizely.Hawksearch.Connector.Handlers;
using Optimizely.Hawksearch.Connector.Handlers.Category;
using Optimizely.Hawksearch.Connector.Handlers.Page;
using Optimizely.Hawksearch.Connector.Handlers.Product;
using Optimizely.Hawksearch.Connector.Initialization;
using StructureMap;
namespace Foundation.Features.Hawksearch.Indexing
{
[InitializableModule]
[ModuleDependency(typeof(BasicHawksearchInitialization))]
public class HawksearchInitialization : IConfigurableModule
{
internal Injected<IContainer> Container;
public void ConfigureContainer(ServiceConfigurationContext context)
{
var container = context.StructureMap();
container.AddHawksearchCategoryIndexing<NodeContent>();
container.AddHawksearchProductIndexing<GenericProduct, GenericVariant>()
.ExtendProductIndexing<GenericProduct, EntriesImagePipe<GenericProduct>>()
.ExtendProductIndexing<GenericProduct, GenericProductAttributesPipe>();
container.AddHawksearchBundleIndexing<GenericBundle, GenericVariant>();
container.AddHawksearchPackageIndexing<GenericPackage, GenericVariant>();
container.AddHawksearchPageIndexing<LocationItemPage>()
.ExtendPageIndexing<LocationItemPage, FoundationPageAttributesPipe<LocationItemPage>>()
.ExtendPageIndexing<LocationItemPage, LocationItemPageAttributesPipe>();
container.AddHawksearchPageIndexing<StandardPage.StandardPage>()
.ExtendPageIndexing<StandardPage.StandardPage, FoundationPageAttributesPipe<StandardPage.StandardPage>>()
.ExtendPageIndexing<StandardPage.StandardPage, StandardPageAttributesPipe>();
}
public void Initialize(InitializationEngine context)
{
Container.Service.Configure(config =>
{
config.For<IFullIndexingChain>().Add(() => FullIndexingChain(Container.Service))
.Transient();
config.For<IIncrementalIndexingChain>().Add(() => IncrementalIndexingChain(Container.Service))
.Transient();
});
}
private IndexingChain FullIndexingChain(IContainer container)
{
return new IndexingChain(container)
.AddHandler<DeletePreviousIndexHandler>()
.AddHandler<CreateIndexHandler>()
.AddHandler<CategoriesIndexingHandler<NodeContent>>()
.AddHandler<HierarchyRebuildHandler>()
.AddHandler<ProductsIndexingHandler<GenericProduct>>()
.AddHandler<BundlesIndexingHandler<GenericBundle>>()
.AddHandler<PackagesIndexingHandler<GenericPackage>>()
.AddHandler<PagesIndexingHandler<LocationItemPage>>()
.AddHandler<PagesIndexingHandler<StandardPage.StandardPage>>()
.AddHandler<RebuildIndexHandler>()
.AddHandler<SetCurrentIndexHandler>();
}
private IndexingChain IncrementalIndexingChain(IContainer container)
{
return new IndexingChain(container)
.AddHandler<GetCurrentIndexHandler>()
.AddHandler<CategoriesIncrementalIndexingHandler<NodeContent>>()
.AddHandler<CategoriesDeletionHandler>()
.AddHandler<HierarchyRebuildHandler>()
.AddHandler<CategoriesCascadeIndexingHandler>()
.AddHandler<ProductsIncrementalIndexingHandler<GenericProduct>>()
.AddHandler<BundlesIncrementalIndexingHandler<GenericBundle>>()
.AddHandler<PackagesIncrementalIndexingHandler<GenericPackage>>()
.AddHandler<PagesIncrementalIndexingHandler<LocationItemPage>>()
.AddHandler<PagesIncrementalIndexingHandler<StandardPage.StandardPage>>()
.AddHandler<EntriesDeletionHandler>()
.AddHandler<PagesDeletionHandler>()
.AddHandler<RebuildIndexHandler>();
}
public void Uninitialize(InitializationEngine context)
{
}
}
}
Updated about 1 year ago