1

I created an index in my Elasticsearch server and I'm using .Net client NEST to connect to it. Some of the index properties have multiple fields and I want to fill just the correct field.

I created the class 'document' to this mappaing. but I do not know how to access fields of property.

this is the mapping I have (summarized):

"mappings": {
      "document": {
        "properties": {

          "baseUniqueID": {
            "type": "keyword"
          },
          "description": {
            "type": "text",
            "fields": {
              "en": {
                "type": "text",
                "analyzer": "english"
              },
              "fa": {
                "type": "text",
                "analyzer": "nofapersian"
              },
              "fr": {
                "type": "text",
                "analyzer": "french"
              }
            }
          },
          "documentDate": {
            "type": "date"
          },
          "documentType_Id": {
            "type": "keyword"
          },
          "id": {
            "type": "long"
          }

        }
      }
    }

and the document class:

public class Document : BaseInt32KeyEntity
    {
        public string BaseUniqueID{ get; set; }

        public int? Weight { get; set; }

        public DateTime DocumentDate { get; set; }

        public string Description { get; set; }

        public int DocumentType_Id { get; set; }
    }
}

How can I make an object of Document to fill just the field I want (here in this example description.en) and then use IndexDocument to add it to Elasticsearch? something like this:

Document doc = new Document();
doc.Description.en = "This is some description";
ElasticClient.IndexDocument(doc);

1
  • I see what you mean. Once I can have a good answer for your question I will post it here. I deleted my previous answer. Commented Jun 13, 2019 at 9:41

1 Answer 1

1

You can update an individual field with the Update API

var client = new ElasticClient();

var documentId = 1;

var partial = new 
{
    Description = "This is some description"
};

var updateResponse = client.Update<Document, object>(documentId, u => u
    .Index("your_index")
    .Doc(partial)
);

The .Index() is only needed if you haven't set up an index convention for the Document type. The document to update is modelled with a partial document because using Document would result in sending default values for value types like the DocumentDate and DocumentType_Id properties.

doc.Description.en = "This is some description";

It's not possible to do this as this is not how multi-fields work. With multi-fields, a single document field input can be analyzed in numerous different ways to serve different search needs. In your example, Description property value will be analyzed 4 different ways:

  1. by the standard analyzer with the base text mapping
  2. by the english analyzer with the .en multi-field mapping
  3. by the nofapersian analyzer with the .fa multi-field mapping
  4. by the french analyzer with the .fr multi-field mapping

The results of analysis will be indexed into the inverted index to allow you to search and query on them, but the original JSON document sent to Elasticsearch will only contain the one "description" field, which is what you will get back when you retrieve the _source for the document (if the _source is stored, which by default it is).

If you wanted to model these as separate fields on the document, the you could introduce a Description type that has the necessary properties

public class Description
{
    public string Standard { get;set; }
    public string English { get;set; }
    public string NoFaPersian{ get;set; }
    public string French{ get;set; }
}

and then index it as an object type mapping, configuring the analyzer for each

public class Document
{
    public string BaseUniqueID { get; set; }
    public int? Weight { get; set; }
    public DateTime DocumentDate { get; set; }
    public Description Description { get; set; }
    public int DocumentType_Id { get; set; }
}

var indexResponse = client.CreateIndex("your_index", c => c
    .Mappings(m => m
        .Map<Document>(mm => mm
            .AutoMap()
            .Properties(p => p
                .Object<Description>(o => o
                    .Name(n => n.Description)
                    .AutoMap()
                    .Properties(pp => pp
                        .Text(t => t.Name(n => n.Standard).Analyzer("standard"))
                        .Text(t => t.Name(n => n.English).Analyzer("english"))
                        .Text(t => t.Name(n => n.NoFaPersian).Analyzer("nofapersian"))
                        .Text(t => t.Name(n => n.French).Analyzer("french"))
                    )
                )
            )
        )
    )       
);

which produces the following create index request

PUT http://localhost:9200/your_index?pretty=true 
{
  "mappings": {
    "document": {
      "properties": {
        "baseUniqueID": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        },
        "weight": {
          "type": "integer"
        },
        "documentDate": {
          "type": "date"
        },
        "description": {
          "type": "object",
          "properties": {
            "standard": {
              "type": "text",
              "analyzer": "standard"
            },
            "english": {
              "type": "text",
              "analyzer": "english"
            },
            "noFaPersian": {
              "type": "text",
              "analyzer": "nofapersian"
            },
            "french": {
              "type": "text",
              "analyzer": "french"
            }
          }
        },
        "documentType_Id": {
          "type": "integer"
        }
      }
    }
  }
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.