16

I'm using the NEST library to interact with ElasticSearch, and I'm trying to figure out a way to build index types/nested objects based on non-type data. The type has the following basic structure.

 public class Entity : DynamicObject
 {
        public string Id { get; set; }
        // a bunch of other simple properties

        public override IEnumerable<string> GetDynamicMemberNames()
        {
                return Data.Select(x => x.Name);
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {

            var dictionary = Data.First(x => x.Name == binder.Name);
            result = dictionary;
            return true;
        }

        // each instance of one these should be a nested object type
        public IList<NestedType> Data { get; set; } 

        public class NestedType
        {
            // How do I make Name be the nest type name?
            public string Name { get; set; }
            public IDictionary<string, string> Values { get; set; } 
        }
}

I want to create a nested object/type for each instance of NestedType. So if there are two instances of NestedType, there will then be two nested objects. I can inherit NestedType from DynamicObject to turn the dictionary into "real" properties that NEST then maps correctly (i.e., turn each dictionary key into a property). The problem is that I can't figure out how to set the name/type of the nested object.

There are two ways to map names that I know of: ElasticType attribute and NestedObject fluent interface. The problem here is that there is a single type that represents multiple nested object types. I could do some runtime type building, but I'd rather not if I can avoid it.

Is there a way to have a method or property be used as the nested object's name/type? Or is there a better approach to mapping this type of data to ElasticSearch (hopefully via NEST)?

Thanks! Erick

EDIT

I updated the entity definition to reflect what I'm doing (using DynamicObject to get the JsonSerializer to do what I want). What I want is the ability for the different dictionaries to have different mappings, (different stemming, analyzers, etc). If there were proper types, I could use the NEST fluent syntax to set it up, but when using dynamic, there is no type for the fluent API to use. Ultimately, I want to mix the fluent API with a string based on strings instead of types. Does this make sense?

2
  • could you provide an example of input, and what you expect to have in ES please ? thx Commented May 4, 2015 at 14:54
  • A sample mapping would be helpful. Could you us a custom json converter attribute, such as this: stackoverflow.com/questions/29173196/… Commented May 5, 2015 at 9:28

1 Answer 1

6
+50

If I understand correctly your intention, Entity object will have only nested objects in it, won't it?

You can try to use dynamic mapping functionality of elasticsearch for entity object. I assume Entity is a root object.

curl -X POST localhost:9200/myindex/entity/_mapping
{"dynamic_templates": [
    {"nested_data_template": {
        "mapping": {
            "type": "nested" },
        "match_mapping_type": "object",
        "path_match": "*" }}]}

path_match: * and match_mapping_type: object mean that for all field names with object as a value nested type mapping will be applied.

Using NEST and Fluent API you can use the following API. IntelliSense will guide you how to build mapping above. ;)

descriptor.DynamicTemplates(DynamicTemplatesDescriptor<Entity>)

Every time when a new property matching this template appears, elasticsearch will update mapping based on dynamic mapping. After a while your mapping will look like:

{
  "entity": {
    "mappings": {
      "entity": {
        "dynamic_templates": [
          {
            "nested_data_template": {
              "mapping": {
                "type": "nested"
              },
              "match_mapping_type": "object",
              "path_match": "*"
            }
          }
        ],
        "properties": {
          "test": {
            "type": "nested",
            "properties": {
              "test": {
                "type": "string"
              },
              "another_property": {
                "type": "string"
              }
            }
          },
          "test1": {
            "type": "nested",
            "properties": {
              "test": {
                "type": "string"
              }
            }
          }
        }
      }
    }
  }
}

Hope this will help!

Sign up to request clarification or add additional context in comments.

1 Comment

Ah, I did not know about the dynamic templates method. This helps me move forward - thanks!

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.