Elasticsearch-net: NEST not setting keyword type for array of strings

Created on 12 Dec 2016  路  2Comments  路  Source: elastic/elasticsearch-net

NEST/Elasticsearch.Net version 5.0.0-rc4:

Elasticsearch version 5.0.0:

We are having an issue while mapping a array of strings. These strings should be keywords but endup being text fields.

So basically:

.Mapping(dm => dm.Keyword(k => k.Name(n => n.ArrayOfTerms)))
Generates this

"arrayOfTerms": {
              "type": "text",
              "fields": {
                 "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                 }
              }
           }

Instead of

"arrayOfTerms": {
              "type": "keyword",
              "fields": {
                 "keyword": {
                    "type": "keyword",
                    "ignore_above": 256
                 }
              }
           }

We are using a json payload with the mapping instead of NEST's fluent interface, which solves the issue, but we would like to know if this is a bug or if we are doing something wrong.

Most helpful comment

.Mapping(dm => dm.Keyword(k => k.Name(n => n.ArrayOfTerms)))

This doesn't look quite right; the mapping for a field should be inside of .Properties() to take effect. Also, the expected mapping does not match the keyword mapping you have, as the mapping is not a multi_field, but the expected mapping is.

Here's an example of automapping. With .AutoMap(), NEST will infer the POCO string property as a text field type mapping, with a keyword sub-field (akin to the mapping that Elasticsearch would infer with dynamic mapping)

```c#
void Main()
{
var pool = new SingleNodeConnectionPool(new Uri($"http://localhost:9200"));
var defaultIndex = "default-index";
var connectionSettings = new ConnectionSettings(pool)
.DefaultIndex(defaultIndex);

var client = new ElasticClient(connectionSettings);

client.CreateIndex(defaultIndex, c => c
    .Mappings(m => m
        .Map<Document>(mm => mm
            .AutoMap()
        )
    )
);

}

public class Document
{
public string[] Property { get; set; }
}

this produces the mapping

```json
{
  "mappings": {
    "document": {
      "properties": {
        "property": {
          "fields": {
            "keyword": {
              "ignore_above": 256,
              "type": "keyword"
            }
          },
          "type": "text"
        }
      }
    }
  }
}

Often, it can be useful to combine automapping with some overrides i.e. let automap automatically map as much as it can and then override the mappings that you want to explicitly change from what will be inferred. Here's what that looks like

```c#
client.CreateIndex(defaultIndex, c => c
.Mappings(m => m
.Map(mm => mm
.AutoMap()
.Properties(p => p
.Keyword(k => k
.Name(n => n.Property)
)
)
)
)
);

which produces the mapping

```json
{
  "mappings": {
    "document": {
      "properties": {
        "property": {
          "type": "keyword"
        }
      }
    }
  }
}

All 2 comments

.Mapping(dm => dm.Keyword(k => k.Name(n => n.ArrayOfTerms)))

This doesn't look quite right; the mapping for a field should be inside of .Properties() to take effect. Also, the expected mapping does not match the keyword mapping you have, as the mapping is not a multi_field, but the expected mapping is.

Here's an example of automapping. With .AutoMap(), NEST will infer the POCO string property as a text field type mapping, with a keyword sub-field (akin to the mapping that Elasticsearch would infer with dynamic mapping)

```c#
void Main()
{
var pool = new SingleNodeConnectionPool(new Uri($"http://localhost:9200"));
var defaultIndex = "default-index";
var connectionSettings = new ConnectionSettings(pool)
.DefaultIndex(defaultIndex);

var client = new ElasticClient(connectionSettings);

client.CreateIndex(defaultIndex, c => c
    .Mappings(m => m
        .Map<Document>(mm => mm
            .AutoMap()
        )
    )
);

}

public class Document
{
public string[] Property { get; set; }
}

this produces the mapping

```json
{
  "mappings": {
    "document": {
      "properties": {
        "property": {
          "fields": {
            "keyword": {
              "ignore_above": 256,
              "type": "keyword"
            }
          },
          "type": "text"
        }
      }
    }
  }
}

Often, it can be useful to combine automapping with some overrides i.e. let automap automatically map as much as it can and then override the mappings that you want to explicitly change from what will be inferred. Here's what that looks like

```c#
client.CreateIndex(defaultIndex, c => c
.Mappings(m => m
.Map(mm => mm
.AutoMap()
.Properties(p => p
.Keyword(k => k
.Name(n => n.Property)
)
)
)
)
);

which produces the mapping

```json
{
  "mappings": {
    "document": {
      "properties": {
        "property": {
          "type": "keyword"
        }
      }
    }
  }
}

Yeah, that did the trick.
Thanks.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

foleta-developers picture foleta-developers  路  5Comments

jhellemann picture jhellemann  路  4Comments

Cnordbo picture Cnordbo  路  4Comments

meriturva picture meriturva  路  3Comments

Mpdreamz picture Mpdreamz  路  5Comments