Paolo Tedesco
Paolo Tedesco

Reputation: 57202

Add a mapping to an existing index template (using NEST attributes)

In my ElasticSearch server, I have an existing index template, which contains some settings and some mappings.

I want to add a mapping for a new type to the template, but since it's not possible to update templates, I need to delete the existing one and recreate it.

Since I would like to keep all the existing settings, I tried getting the existing definition, add the mapping to it and then delete/recreate, like in this example:

using Nest;
using System;

public class SomeNewType {
    [ElasticProperty(Index = FieldIndexOption.NotAnalyzed)]
    public string SomeField { get; set; }
    [ElasticProperty(Index = FieldIndexOption.Analyzed)]
    public string AnotherField { get; set; }
}

class Program {
    static void Main(string[] args) {
        var settings = new ConnectionSettings(uri: new Uri("http://localhost:9200/"));
        var client = new ElasticClient(settings);
        var templateResponse = client.GetTemplate("sometemplate");
        var template = templateResponse.TemplateMapping;
        client.DeleteTemplate("sometemplate");
        // Add a mapping to the template somehow...
        template.Mappings.Add( ... );
        var putTemplateRequest = new PutTemplateRequest("sometemplate") {
            TemplateMapping = template
        };
        client.PutTemplate(putTemplateRequest);
    }
}

However, I cannot find a way to add a mapping to the template definition using the ElasticProperty attributes, like in

client.Map<SomeNewType>(m => m.MapFromAttributes());

Is it possible to create a RootObjectMapping to add to the Mappings collection with something similar to MapFromAttributes?

Upvotes: 2

Views: 2872

Answers (1)

Dusty
Dusty

Reputation: 3971

You can do this by using the more robust PutMappingDescriptor to get a new RootObjectMapping, then add that into the collection returned by your GET _template request, like so:

var settings = new ConnectionSettings(uri: new Uri("http://localhost:9200/"));
var client = new ElasticClient(settings);

var templateResponse = client.GetTemplate("sometemplate");
var template = templateResponse.TemplateMapping;
// Don't delete, this way other settings will stay intact and the PUT will override ONLY the mappings.
// client.DeleteTemplate("sometemplate");

// Add a mapping to the template like this...
PutMappingDescriptor<SomeNewType> mapper = new PutMappingDescriptor<SomeNewType>(settings);
mapper.MapFromAttributes();
RootObjectMapping newmap = ((IPutMappingRequest) mapper).Mapping;

TypeNameResolver r = new TypeNameResolver(settings);
string mappingName = r.GetTypeNameFor(typeof(SomeNewType));

template.Mappings.Add(mappingName, newmap);

var putTemplateRequest = new PutTemplateRequest("sometemplate")
{
    TemplateMapping = template
};

var result = client.PutTemplate(putTemplateRequest);

Note: TypeNameResolver is in the Nest.Resolvers namespace

As noted in the comment above, I recommend that you NOT delete the old template if the mappings are the only thing that needs updated, otherwise you will need to copy all of the other relevant settings into your new request.

Upvotes: 3

Related Questions