0
votes

I Have an index with the following mappings:

{
    "winnings": {
        "mappings": {
            "properties": {
                "handId": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "id": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "playerId": {
                    "type": "text",
                    "fields": {
                        "keyword": {
                            "type": "keyword",
                            "ignore_above": 256
                        }
                    }
                },
                "value": {
                    "type": "float"
                }
            }
        }
    }
}

generated from the class:

public class ElasticWinnings
    {
        public Guid Id { get; set; }
        public Guid HandId { get; set; }
        public Guid PlayerId { get; set; }
        public decimal Value { get; set; }
    }

I created that in nest with the ConnectionSettings:

.DefaultMappingFor<ElasticWinnings>(u =>
    u.IndexName("winnings")
         .IdProperty(x => x.Id)
 );

when I try and run the following query:

var result = _client.Search<ElasticWinnings>(s =>
    s.Aggregations(a =>
            a.Terms("term_Agg", t =>
                t.Field(f => f.PlayerId)
                    .Aggregations(aa =>
                        aa.Sum("sum", sum => 
                            sum.Field(f => f.Value))
                        )
            ))
  );

I get a 400 back, with the error:

type: illegal_argument_exception Reason: "Fielddata is disabled on text fields by default

It creates this query:

{  
   "aggs":{  
      "term_Agg":{  
         "aggs":{  
            "sum":{  
               "sum":{  
                  "field":"value"
               }
            }
         },
         "terms":{  
            "field":"playerId"
         }
      }
   }
}

If I changed that query to:

{  
   "aggs":{  
      "term_Agg":{  
         "aggs":{  
            "sum":{  
               "sum":{  
                  "field":"value"
               }
            }
         },
         "terms":{  
            "field":"playerId.keyword"
         }
      }
   }
}

and used that in postman, it works.

I am not sure why it is not putting the .keyword into the query. Is it the way the nest client is configured, the indicies or the query?

2

2 Answers

3
votes

You need to change your query a little bit to tell NEST to use keyword field instead of text, you can do this with .Suffix extension method. Link to docs.

var result = _client.Search<ElasticWinnings>(s =>
    s.Aggregations(a =>
            a.Terms("term_Agg", t =>
                t.Field(f => f.PlayerId.Suffix("keyword"))
                    .Aggregations(aa =>
                        aa.Sum("sum", sum => 
                            sum.Field(f => f.Value))
                        )
            ))
  );

Hope that helps.

0
votes

The solution I found was to add [Keyword] to the PlayerId property in ElasticWinnings class.

I kept the .DefaultMappingFor<ElasticWinnings>(u => u.IndexName("winnings") in the creation of the ConnectionSettings class, but added this before the Elastic client is returned:

var client = new ElasticClient(settings);

client.Indices.Create("winnings", c =>
    c.Map<ElasticWinnings>(m => m.AutoMap())
);

Without adding the section above, it did not apply the attributes. This changed my mappings (http://localhost:9200/winnings/_mappings) to

{
    "winnings": {
        "mappings": {
            "properties": {
                "handId": {
                    "type": "keyword"
                },
                "id": {
                    "type": "keyword"
                },
                "playerId": {
                    "type": "keyword"
                },
                "value": {
                    "type": "double"
                }
            }
        }
    }
}

This is the docs about setting up the mappings https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/fluent-mapping.html