mcating
mcating

Reputation: 1102

ElasticSearch NEST: Create an index through ElasticClient by specifying json

We allow the client to define custom analyzers at the time they create an index. We would prefer to specify this in json to provide maximum flexibility and understandability via the underlying ElasticSearch documentation.

I would like to create an index using an arbitrary description of analyzers, mappers, etc., defined in a json string. Using sense, my command is

PUT /my_index
{
    "settings": 
    {
        "analysis": 
        {
            "char_filter" : 
            {
                "my_mapping" : 
                {
                    "type" : "mapping",
                    "mappings" : [".=>,", "'=>,"]
                }
            },
            "analyzer": 
            {
                "my_analyzer": 
                {
                    "type":         "custom",
                    "tokenizer":    "standard",
                    "filter":       ["lowercase" ],
                    "char_filter" : ["my_mapping"]
                }
            }
         }
      }
   }
}

Ideally, my code would look something like

string json = RetrieveJson();
ElasticSearchClient client = InitializeClient();
client.CreateIndexUsingJson( json ); // this is the syntax I can't figure out

The post here attempts to do this by instantiating an IndexSettings then calling Add( "analysis", json ), but Add is not a function on the ElasticSearch library version I'm using.

The options I can imagine include:

  1. Somehow using the ElasticClient.Raw.IndicesCreatePost or something analogous
  2. Deserializing the json string into an IndexSettings object via IndexSettingsConverter.ReadJson(), and then applying that through ElasticClient.CreateIndex(ICreateIndexRequest)

Both of these mechanisms have very scant documentation.

I'm absolutely trying to avoid the lambda function versions of CreateIndex, since it would be miserable to translate the user's json into lamdba expressions, only to immediately translate them back into json deep in NEST.

Other options or concrete examples of #1 or #2 above are very much appreciated, as is a recommended approach to solving this problem.

Upvotes: 4

Views: 6290

Answers (3)

Airn5475
Airn5475

Reputation: 2492

Okay after updating to Elasticsearch NEST v6.0.2 I had to modify my code and wanted to post it out here for someone else. The changes include passing CreateResponse in as a type for the function and using the ApiCall property on the response.

public bool CreateIndex(string indexName, string json)
{
    var response = _client.LowLevel.IndicesCreate<CreateResponse>(indexName, json);
    return response.ApiCall.Success;
}  

Hope this saves someone time!

Upvotes: 0

mcating
mcating

Reputation: 1102

Easiest solution was an implementation of Option #1 from the original question.

public void CreateIndex(string indexName, string json)
{
    ElasticClient client = GetClient();
    var response = _client.Raw.IndicesCreatePost(indexName, json);
    if (!response.Success || response.HttpStatusCode != 200)
    {
        throw new ElasticsearchServerException(response.ServerError);
    }
}

After tinkering around with converters and JsonReaders and JsonSerializers, I found that the IndexSettingsConverter didn't seem to properly deserialize arbitrary settings json into a valid IndexSettings object. Sensing a rabbit hole, I took Manolis' suggestion and figured out how to apply the arbitrary json directly against the ElasticClient.IElasticsearchClient to avoid having to reverse-engineer security and connection details.

Painful effort to come to this conclusion, and completely impossible without working through a whole lot of undocumented NEST code.

Upvotes: 7

Manolis
Manolis

Reputation: 738

If you want to do something like the one you describe above then you could simply use an HttpClient and send the request for creating the index to your elasticsearch server. At this case, you can include your JSON in the content of the request.

Try the below:

public async void CreateIndex() {
            using (var httpClient = new HttpClient()) {
                using (var request = new HttpRequestMessage(HttpMethod.Put, new Uri("http://elastic_server_ip/your_index_name"))) {
                    var content = @"{ ""settings"" : { ""number_of_shards"" : 1 } }";
                    request.Content = new StringContent(content);
                    var response = await httpClient.SendAsync(request);
                }
            }
        }

This specific snippet will create an index to the specified endpoint with one shard, one replica (default) and default settings and mappings. Change the content variable with your json.

Upvotes: 2

Related Questions