SDKits / ExamineX

Issue tracker for ExamineX
https://examinex.online
5 stars 0 forks source link

Searching custom index fails if analyzerName is default when adding index. #71

Closed hallojoe closed 1 year ago

hallojoe commented 1 year ago

Umbraco 10.1.0 ExamineX 4.0.0-beta 2

When adding a custom Examine index, this code will do the job:

.AddExamineLuceneIndex<TestUmbracoIndex, ConfigurationEnabledDirectoryFactory>(nameof(TestUmbracoIndex));

A default analyzer is set when analyzer argument is not given.

This code will work as far as getting indexes created and populated on the Azure Search Service:

.AddExamineXAzureSearchIndex<TestUmbracoIndexX>(nameof(TestUmbracoIndexX));

When querying the index from code or back-office, then this exception is thrown:

Exception Details
System.ArgumentException, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e: 'analyzer' cannot be null or whitespace. (Parameter 'analyzer')

at ExamineX.AzureSearch.AzureSearchQuery.A(AzureSearchFieldReferences , String )
   at ExamineX.AzureSearch.AzureSearchQuery..ctor(SearchClient indexClient, ILoggerFactory loggerFactory, String analyzer, String category, AzureSearchFieldReferences fields, BooleanOperation occurance)
   at ExamineX.AzureSearch.AzureSearchSearcher.CreateQuery(String category, BooleanOperation defaultOperation)
   at Umbraco.Cms.Web.BackOffice.Controllers.ExamineManagementController.GetSearchResults(String searcherName, String query, Int32 pageIndex, Int32 pageSize)
   at lambda_method938(Closure , Object , Object[] )
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.SyncObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Logged|12_1(ControllerActionInvoker invoker)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)

The fix is easy - give analyzerName argument:

.AddExamineXAzureSearchIndex<TestUmbracoIndexX>(nameof(TestUmbracoIndexX), null, "standard"));

Suggestion: analyzerName default to standard or it is made non-nullable.

Shazwazza commented 1 year ago

There's code in ExamineX that does this within the underlying AddExamineXAzureSearchIndex method:

// no explicit analyzer, set as the orig
if (analyzerName == null && originalNamedOptions.Analyzer != null)
{
    analyzerName = LuceneAzureSearchConverter.ToAzureSearchAnalyzer(
        originalNamedOptions.Analyzer.GetType()).ToString();
}

What should occur is that some validation is done when there isn't any IOptionsMonitor<LuceneDirectoryIndexOptions> for that named index.

In your case you could/should add a service to DI for IConfigureNamedOptions just like Umbraco does here https://github.com/umbraco/Umbraco-CMS/blob/v10/contrib/src/Umbraco.Examine.Lucene/DependencyInjection/ConfigureIndexOptions.cs

Shazwazza commented 1 year ago

I've added a fix for this so that it falls back to StandardAnalyzer if no options are configured at all.

Shazwazza commented 1 year ago

Will be out with the 4.0.0 RTM release this week.