# Fluent Mapping Dictionary\<string, MyDto\>

**URL:** <https://discuss.elastic.co/t/fluent-mapping-dictionary-string-mydto/163434>\
**Category:** Elasticsearch\
**Created:** [January 8, 2019, 8:34pm UTC](https://discuss.elastic.co/t/fluent-mapping-dictionary-string-mydto/163434 "2019-01-08T20:34:26Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Hossein\_Nassiri](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/hossein_nassiri/32/39579_2.png) [@Hossein\_Nassiri](https://discuss.elastic.co/u/Hossein_Nassiri)\
**Post date:** [January 8, 2019, 8:34pm UTC](https://discuss.elastic.co/t/fluent-mapping-dictionary-string-mydto/163434/1 "2019-01-08T20:34:26Z")

</div>

Hi

I have a dictionary which I want to map using fluent mapping, and for some properties of MyDto class, I need to add normalizer.  
// ...  
// Dictionary\<string, MyDto\> SomeCollection {get;set;}  
// ...  
// class MyDto {  
// Name {get;set;}  
// }

How can I map it?

---

<div class="post-metadata">

**Author:** ![forloop](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/forloop/32/9021_2.png) [@forloop](https://discuss.elastic.co/u/forloop)\
**Post date:** [January 9, 2019, 12:41am UTC](https://discuss.elastic.co/t/fluent-mapping-dictionary-string-mydto/163434/2 "2019-01-09T00:41:32Z")

</div>

[I answered your same question on stackoverflow](https://stackoverflow.com/a/54100167/1831); will include here for completeness.

It's not possible to add this as an explicit mapping, but it is through a dynamic template.

Let's look at why it's not possible through explicit mapping. Consider how `Dictionary<string, MyDto> SomeProperty` will serialize to JSON. For example

```auto
client.IndexDocument(new MyEntity 
{
    SomeProperty = new Dictionary<string, UserQuery.MyDto>
    {
        { "field_1", new MyDto { Name = "foo" } },
        { "field_2", new MyDto { Name = "bar" } }
    }
});

```

by default will serialize as

```json
{
  "someProperty": {
    "field_1": {
      "name": "foo"
    },
    "field_2": {
      "name": "bar"
    }
  }
}

```

If we wanted to apply an explicit mapping to `MyDto.Name`, we would need to know at the point of mapping, all of the dictionary keys that will be used.

You can however, [configure a dynamic template that will map any `MyDto.Name` as a `keyword` type, using `path_match`](https://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-templates.html#path-match-unmatch)

```auto
private static void Main()
{
    var defaultIndex = "my_index";
    var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));

    var settings = new ConnectionSettings(pool)
        .DefaultIndex(defaultIndex);

    var client = new ElasticClient(settings);
    
	if (client.IndexExists(defaultIndex).Exists)
		client.DeleteIndex(defaultIndex);
	
    var createIndexResponse = client.CreateIndex(defaultIndex, c => c
		.Settings(s => s
			.NumberOfShards(1)
			.NumberOfReplicas(0)
		)
		.Mappings(m => m
			.Map<MyEntity>(mm => mm
                .AutoMap()
                .DynamicTemplates(dt => dt
                    .DynamicTemplate("MyDto", dtd => dtd
                        .PathMatch("someProperty.*.name")
                        .Mapping(dm => dm
                            .Keyword(k => k)
                        )
                    )
                )
                .Properties(p => p
                    .Object<Dictionary<string, MyDto>>(o => o
                        .Name(n => n.SomeProperty)
                    )
                )
            )
		)
	);
    
    var indexResponse = client.Index(new MyEntity 
    {
        SomeProperty = new Dictionary<string, UserQuery.MyDto>
        {
            { "field_1", new MyDto { Name = "foo" } },
            { "field_2", new MyDto { Name = "bar" } }
        }
    }, i => i.Refresh(Refresh.WaitFor));
    
    var mappingResponse = client.GetMapping<MyEntity>();
}

public class MyEntity
{
    public Dictionary<string, MyDto> SomeProperty { get; set; }
}

public class MyDto
{
    public string Name { get; set; }
}

```

The mapping response confirms that `someProperty.field_1.name` and `someProperty.field_2.name` are mapped as `keyword`

```json
{
  "my_index" : {
    "mappings" : {
      "myentity" : {
        "dynamic_templates" : [
          {
            "MyDto" : {
              "path_match" : "someProperty.*.name",
              "mapping" : {
                "type" : "keyword"
              }
            }
          }
        ],
        "properties" : {
          "someProperty" : {
            "properties" : {
              "field_1" : {
                "properties" : {
                  "name" : {
                    "type" : "keyword"
                  }
                }
              },
              "field_2" : {
                "properties" : {
                  "name" : {
                    "type" : "keyword"
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

```

### An aside on mapping explosion

You may want to consider adding a property to `MyDto` to hold the dictionary key, and use a `List<MyDto>` or similar collection [mapped as a `nested` datatype](https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html), rather than `Dictionary<string, MyDto>`, if users can add any arbitrary key names they wish. With a high cardinality of dictionary keys, you run the risk of a mapping explosion and hitting the [maximum number of fields soft limit](https://www.elastic.co/guide/en/elasticsearch/reference/master/mapping.html#mapping-limit-settings) and a lot of sparse fields, which can affect performance. With a `List<MyDto>` property type, you would not have this issue and can still query on the key field, at the expense of the trade-off that a `List<MyDto>` may be less optimal for your application code than a `Dictionary<string, MyDto>`. Something to consider 🙂

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/elastic/original/3X/1/a/1ac57faf039f6b580b3f104ef42a2a89e41014de.png) [@system](https://discuss.elastic.co/u/system)\
**Post date:** [February 6, 2019, 12:41am UTC](https://discuss.elastic.co/t/fluent-mapping-dictionary-string-mydto/163434/3 "2019-02-06T00:41:32Z")

</div>

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.
