Search code examples
c#elasticsearchnest

How to create document with an index in ElasticSearch using NEST library in .NET?


I am trying to use elastic search for the first time in C# and I am trying to create a document which is similar to a row in sql.

For what I understand, index is similar to a table and document is a row. I tried using CreateDocumentAsync method but it does not have any parameter to pass in the index so I am not sure how do I create a document with a particular index. I cannot use default index because our product can have many indices. First I am checking if the index exists and if it does not then it creates the index and then the document

Some code here

public async Task<CreateResponse> CreateDocumentAndIndex<T>(T document, string index) where T : class
{
    CreateResponse response = new(); 
    if (_client.Indices.Exists(index).Exists)
    {
        response = await _client.CreateDocumentAsync<T>(document);
    }
    else
    {
        await _client.IndexAsync(document, idx => idx.Index(index));
        response = await _client.CreateDocumentAsync<T>(document);
    }         
    return response;
}

Now to use this I have a function that calls this method

var response = await elasticSearchClient.CreateDocumentAndIndex<DbContextEventData>(eventData,"test");

But it gives me an error when it is trying to create a document. Is there a way to pass in index when creating a row/document in elastic search


Solution

  • The question is tagged elasticsearch-5, so assuming you're using NEST 5.6.6, the index can be specified at the same time as creating a document

    var client = new ElasticClient();
    
    var createResponse = await client.CreateAsync(new { foo = "bar" }, c => c
        .Index("my-index") // index
        .Type("_doc") // document type
        .Id("1") // document id
    );
    

    EDIT:

    Since you're using Elasticsearch 6.3.0, you must use the latest NEST 6.x client, which at time of writing is 6.8.10. With NEST 6.8.10, a create document API call is as follows

    private static void Main()
    {
        var pool = new SingleNodeConnectionPool(new Uri($"http://localhost:9200"));
        var settings = new ConnectionSettings(pool)
            .DisableDirectStreaming()
            .PrettyJson()
            .DefaultTypeName("_doc") // doc types are gone in future versions, so best to index with this default doc type name
            .OnRequestCompleted(LogToConsole);
            
        var client = new ElasticClient(settings);
        
        if (client.IndexExists("my-index").Exists) 
        {
            client.DeleteIndex("my-index");
        }
    
        var document = new MyDocument
        {
            Foo = "Bar",
            Baz = 1
        };
    
        var createResponse = client.Create(document, c => c
            .Index("my-index") // index
            .Id("1") // document id
        );
        
        var returnedDocument = client.Get<MyDocument>("1", g => g.Index("my-index"));
    }
    
    public class MyDocument
    {
        public string Foo { get; set; }
        
        public int Baz { get; set; }
    }
    
    private static void LogToConsole(IApiCallDetails callDetails) 
    {
        if (callDetails.RequestBodyInBytes != null)
        {
            var serializer = new JsonSerializer();
            var jObjects = new List<JObject>();
            using (var sr = new StringReader(Encoding.UTF8.GetString(callDetails.RequestBodyInBytes)))
            using (var jsonTextReader = new JsonTextReader(sr))
            {
                jsonTextReader.SupportMultipleContent = true;
                while (jsonTextReader.Read())
                    jObjects.Add((JObject)JObject.ReadFrom(jsonTextReader));
            }
    
            var formatting = jObjects.Count == 1
                ? Newtonsoft.Json.Formatting.Indented
                : Newtonsoft.Json.Formatting.None;
            var json = string.Join("\n", jObjects.Select(j => j.ToString(formatting)));
            Console.WriteLine($"{callDetails.HttpMethod} {callDetails.Uri} \n{json}");
        }
        else
        {
            Console.WriteLine($"{callDetails.HttpMethod} {callDetails.Uri}");
        }
    
        Console.WriteLine();
    
        if (callDetails.ResponseBodyInBytes != null)
        {
            Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
                     $"{Encoding.UTF8.GetString(callDetails.ResponseBodyInBytes)}\n" +
                     $"{new string('-', 30)}\n");
        }
        else
        {
            Console.WriteLine($"Status: {callDetails.HttpStatusCode}\n" +
                     $"{new string('-', 30)}\n");
        }
    }
    

    which logs the following to the console

    PUT http://localhost:9200/my-index/_doc/1/_create?pretty=true
    {
      "foo": "Bar",
      "baz": 1
    }
    
    Status: 201
    {
      "_index" : "my-index",
      "_type" : "_doc",
      "_id" : "1",
      "_version" : 1,
      "result" : "created",
      "_shards" : {
        "total" : 2,
        "successful" : 1,
        "failed" : 0
      },
      "_seq_no" : 0,
      "_primary_term" : 1
    }
    
    ------------------------------
    
    GET http://localhost:9200/my-index/_doc/1?pretty=true
    
    Status: 200
    {
      "_index" : "my-index",
      "_type" : "_doc",
      "_id" : "1",
      "_version" : 1,
      "found" : true,
      "_source" : {
        "foo" : "Bar",
        "baz" : 1
      }
    }
    
    ------------------------------