ElasticSerach filter tags is case sensetive?

I see that by default the accelerator add filters, brands etc incloding case to the index. and is seames like we need to match the casing on a brand to get a hit when we filter on tags, how can we make filtering case insensetive?

tags {
“key”: “Brand”,
“value”: “Hugo Boss”
},
{
“key”: “ProductType”,
“value”: “EdT”
},
{
“key”: “ScentType”,
“value”: “Frisk”
},
{
“key”: “Size”,
“value”: “125 ml”
}

Litium version: 7.4

In the document setup you will tell the keyword analyzer to use the lowercase normalizer

        public class TagItem
        {
            [Keyword]
            public string Key { get; set; }

            [Keyword(EagerGlobalOrdinals = true, Normalizer = "lowercase")]
            public string Value { get; set; }
        }

You need now to remove the search index from elasticsearch or change the index prefix so a new search index is created. The above change is not reflected in existing index.

If you have other normalizer or analyzer you want to use you can configure them in the index configuration, example below to add a custom normalizer

    public class ProductIndexConfiguration : MultilingualIndexConfigurationBase<ProductDocument>
    {
        protected override CreateIndexDescriptor BuildIndexDescriptor(CultureInfo cultureInfo, CreateIndexDescriptor descriptor)
        {
            return base.BuildIndexDescriptor(cultureInfo, descriptor)
                // add the custom normalizer that will be used together with the keyword analyzer.
                .Settings(s => s.Analysis(a => a.Normalizers(n => n.Custom("my_normalizer", cn => cn.Filters("lowercase")))));
        }

Documentation about normalizers

If i add this, delete the indexes, rebuild and start the application, it will not build an a product index at all :confused:

If i revert, it start building

The error i get:

Failed to parse mapping [_doc]: normalizer [lowercase] not found for field [value]" CausedBy: “Type: mapper_parsing_exception Reason: “normalizer [lowercase] not found for field [value]””",

Full:

{ "time": "2020-08-25 10:54:00.5812", "level": "Error", "appdomain": "16", "activityid": "5829fe27-3738-4643-b903-2d5cdc8fae06", "server": "DESKTOP-BJS9J12", "logger": "Litium.Search.Indexing.IndexQueueService", "message": "Error in building index document for Litium.Accelerator.Search.ProductDocument with 5515744a-7712-4c17-8d16-a5087685c289 and Index, @{ id = ProductDocument:5515744a-7712-4c17-8d16-a5087685c289, primaryTerm = 1, sequenceNumber = 168282, version = 122 }: Fj\u00e4rrservern returnerade ett fel: (400) Felaktig beg\u00e4ran.. Call: Status code 400 from: PUT \/productdocument.sv-se. ServerError: Type: mapper_parsing_exception Reason: \"Failed to parse mapping [_doc]: normalizer [lowercase] not found for field [value]\" CausedBy: \"Type: mapper_parsing_exception Reason: \"normalizer [lowercase] not found for field [value]\"\"", "exception": "Elasticsearch.Net.ElasticsearchClientException: Fj\u00e4rrservern returnerade ett fel: (400) Felaktig beg\u00e4ran.. Call: Status code 400 from: PUT \/productdocument.sv-se. ServerError: Type: mapper_parsing_exception Reason: \"Failed to parse mapping [_doc]: normalizer [lowercase] not found for field [value]\" CausedBy: \"Type: mapper_parsing_exception Reason: \"normalizer [lowercase] not found for field [value]\"\" ---> System.Net.WebException: Fj\u00e4rrservern returnerade ett fel: (400) Felaktig beg\u00e4ran.\r\n   at System.Net.HttpWebRequest.GetResponse()\r\n   at Elasticsearch.Net.HttpWebRequestConnection.Request[TResponse](RequestData requestData) in c:\\Projects\\elastic\\net-7\\src\\Elasticsearch.Net\\Connection\\HttpWebRequestConnection.cs:line 59\r\n   --- End of inner exception stack trace ---\r\n   at Litium.Search.SearchExtensions.EnsureSuccessStatusCode[T](T response)\r\n   at Litium.Application.Search.IndexNamingServiceImpl.ConfigurateIndex(String indexName, IIndexMappingConfiguration configuration, CultureInfo cultureInfo)\r\n   at Litium.Application.Search.IndexNamingServiceImpl.<>c__DisplayClass9_1.<GetCurrentIndexName>b__1()\r\n   at System.Lazy`1.CreateValue()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Lazy`1.get_Value()\r\n   at Litium.Search.Indexing.MultilingualIndexDocumentBuilderBase`1.<Index>b__2_0(ValueTuple`2 x)\r\n   at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()\r\n   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)\r\n   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)\r\n   at Litium.Search.Indexing.MultilingualIndexDocumentBuilderBase`1.<Index>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Litium.Application.Search.Indexing.IndexQueueServiceImpl.<ProcessItem>d__17.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at Litium.Application.Search.Indexing.IndexQueueServiceImpl.<>c__DisplayClass15_0.<<ProcessQueue>b__0>d.MoveNext()", "eventProperties": {  } }

Do i need to config it like this? even if i dont want anything custom?

    protected override CreateIndexDescriptor BuildIndexDescriptor(CultureInfo cultureInfo, CreateIndexDescriptor descriptor)
    {
		return base.BuildIndexDescriptor(cultureInfo, descriptor)
			.Settings(s => s.Analysis(a => a.Normalizers(n => n.Custom("lowercase", cn => cn.Filters("lowercase")))));
	}

A simple normalizer called lowercase ships with elasticsearch and can be used. Custom normalizers can be defined as part of analysis settings as follows.

Is from the above linked documentation from Elastic and from that I assume it should work without creating an custom analyser. When I check older documentation (Elasticsearch 6.x) this sentence is not there.

What version of Elasticsearch are you using?
Is it working if you create a custom normalizer?

Yes, it works now after addin that code, am using the elastic docker file from the education on git thanks.

Oki, so this did not fully solve the problem, or is solved the Search part, but this made our aggregatons lose there casing as well :slight_smile:

How do I crate a subfield?

We basicaly need to do what the Accepted Answer suggest.

My current workaound is to add a duplicat Value, that is not normalized, and we use that to display the aggregations. This works fine, but i dont like the duplication, but it might be the only oprion?

    public class TagItem
    {
		[Keyword(Normalizer = "lowercase")]
		public string Key { get; set; }

		[Keyword(EagerGlobalOrdinals = true, Normalizer = "lowercase")]
		public string Value { get; set; }

		[Keyword]
		public string DisplayName { get; set; }
	}

If you remove the Keyword attribute on the Value-property it should automatic create a mapping with a keyword sub field. But that will also make you to change how the filtering is working and using the sub field instead.

See https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/multi-fields.html for references, you can modify the mapping inside ProductIndexConfiguration.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.