November Happy Hour will be moved to Thursday December 5th.

EPiServer Search (Lucene) multiple indexes?

Vote:
 

Hi,

is it possible to store different content types in different search indexes?
I can't figure out how to specify what namedIndex to use. It seems that EPi only uses the default one?

Can someone please shed some light on this?

Thanks!

#140502
Oct 21, 2015 13:56
Vote:
 

Hi Robert,

I've defined a new named index in web.config and created the following init module:

[InitializableModule]
[ModuleDependency(typeof(EPiServer.Web.InitializationModule))]
public class SearchInitialization : IInitializableModule
{
    public void Initialize(InitializationEngine context)
    {
        IndexingService.DocumentAdding += IndexingService_DocumentAdding;
    }

    private void IndexingService_DocumentAdding(object sender, EventArgs e)
    {
        var args = e as AddUpdateEventArgs;
		
		// index all documents in custom named index
        if (args != null)
        {
            args.NamedIndex = "custom";
        }
    }

    public void Uninitialize(InitializationEngine context)
    {
        IndexingService.DocumentAdding -= IndexingService_DocumentAdding;
    }
}

In theory, all documents should now be indexed in custom named indexed, but they're still indexed in default one.

I've checked IndexingService and IndexingServiceHandler.
Method that's responsible for indexing documents have something like this in its body:

EPiServer.Search.IndexingService.IndexingService.OnDocumentAdding(this, new AddUpdateEventArgs(documentFromSyndicationItem, namedIndex.Name));
this.WriteToIndex(id, documentFromSyndicationItem, namedIndex);

This means that args.NamedIndex = "custom" in my init module will never be taken into account.

IndexingServiceHandler should return namedIndex instead of namedIndex.Name since strings are immutable.

I'm afraid you'll have to write your own implementation of IIndexingService.

#140803
Oct 30, 2015 11:41
Vote:
 

My solution has been to override EPiServer.Search.SearchHandler and then register it with the IoC instead of the default EPiServer.Search.SearchHandler

I used an Attribute on the content type to specify what NamedIndex to use.

NansenSearchConfig.NamedIndexTypes is a list of types to search in, registered at startup

        /// <summary>
        /// Will updated the namedIndex of the IndexRequestItem if the type has the <seealso cref="SearchIndex"/> attribute
        /// </summary>
        /// <param name="item">The item to index</param>
        /// <param name="namedIndexingService"></param>
        public override void UpdateIndex(IndexRequestItem item, string namedIndexingService)
        {
            Type itemType = GetContentType(item);
            if (itemType != null)
            {
                Log(Level.Debug, "Updating index for content id '{0}' of type '{1}'", item.Id, itemType.Name);
                var attr = itemType.GetCustomAttribute<NamedIndexAttribute>();
                if (attr != null)
                {
                    if (!NamedIndexes.Contains(attr.NamedIndex))
                    {
                        Log(Level.Error, "NamedIndex '{0}' specified on content type '{1}' does not exist!", attr.NamedIndex, itemType.Name);
                    }
                    else
                    {
                        item.NamedIndex = attr.NamedIndex;
                        Log(Level.Debug, "Setting NamedIndex for ContentType '{0}' to namedIndex '{1}'", itemType.Name, attr.NamedIndex);
                    }
                }
            }
            base.UpdateIndex(item, namedIndexingService);
        }

 

        /// <summary>
        /// Will get the type from the IndexRequestItem
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        private Type GetContentType(IndexRequestItem item)
        {
            if (string.IsNullOrEmpty(item.ItemType))
            {
                return null;
            }
            string[] types = item.ItemType.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            string typeName = types.FirstOrDefault();
            return NansenSearchConfig.NamedIndexTypes.FirstOrDefault(p => p.FullName == typeName);
        }

 

    /// <summary>
    /// Attribute used to specify if an item should be indexed in a specific named index
    /// </summary>
    [AttributeUsage(validOn: AttributeTargets.Class, AllowMultiple = false)]
    public class NamedIndexAttribute : Attribute
    {
        public NamedIndexAttribute() { }
        public NamedIndexAttribute(string namedIndex)
        {
            this.NamedIndex = namedIndex;
        }
        public string NamedIndex { get; set; }
    }

 

#141062
Nov 09, 2015 10:44
This topic was created over six months ago and has been resolved. If you have a similar question, please create a new topic and refer to this one.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.