.netasp.net-coreelasticsearchnestelasticsearch-net

Elasticsearch NEST add normalizer on all keyword fields with NoopPropertyVisitor


Im trying to add custom normalizer on all keyword fields. Im using NoonPropertyVisitor to override:

public class CustomNormalizerVisitor : NoopPropertyVisitor
    {
        public override void Visit(IKeywordProperty type, PropertyInfo propertyInfo,  ElasticsearchPropertyAttributeBase attribute)
        {
            type.Normalizer = "customnormalizer";
        }
    }

then I use it here:

CustomNormalizerVisitor visitor = new CustomNormalizerVisitor();

        client.Indices.Create(indexName, i => i
        .Settings(s => s
            .Analysis(a => a
                .Normalizers(n => n.
                    Custom("customnormalizer", cn => cn
                     .Filters(new string[] { "lowercase", "asciifolding" })))))
        .Map<ELSEntity>(m => m
         .AutoMap(visitor)
             .Properties(p => p
                 .Nested<FieldValue>(ne => ne.Name(n => n.Fields).Enabled(false)))));

but when i go on mapping, I do not see that normalizer is applied on keyword fields. I test with type.DocValues = false on IBooleanProperty and its working.

This is mapping:

    {
  "elsentity": {
    "mappings": {
      "properties": {
        "assets": {
          "properties": {
            "active": {
              "type": "boolean",
              "doc_values": false
            },
            "assetCreationDate": {
              "type": "date"
            },
            "assetSourceId": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "assetStatusId": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "assetType": {
              "type": "integer"
            },
            "categoryId": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },
            "default": {
              "type": "boolean",
              "doc_values": false
            },
            "id": {
              "type": "text",
              "fields": {
                "keyword": {
                  "type": "keyword",
                  "ignore_above": 256
                }
              }
            },

Not sure maybe its because keyword is under fields? I tried to override different properties on keyword, but not working. I need Text and Keyword both on string fields because of different queries.


Solution

  • I think I found solution. In NooPPropertyVisitor, with type.Fields we can add keyword field and set there Normalizer, additional on text field we can set Analyzer and this is how it looks:

     public class CustomNormalizerVisitor : NoopPropertyVisitor
    {
        public override void Visit(ITextProperty type, PropertyInfo propertyInfo,  ElasticsearchPropertyAttributeBase attribute)
        {
            Dictionary<PropertyName, IProperty> container = new Dictionary<PropertyName, IProperty>();
            
            container.Add(new PropertyName("keyword"), new KeywordProperty() { Normalizer = "customnom"});
           
            type.Analyzer = "custom";
            
            type.Fields = new Nest.Properties(container);
            
        }
    }