I want to map dynamically the properties inside a JObject in C# using Nest. The goal is to map every string field of the object as SearchAsYouType. I thought about 3 ways of doing that that didn't work:
public class Forfait
{
public long Id { get; set; }
[SearchAsYouType()]
public string Data { get; set; }
}
public class Act
{
public JObject Entity;
}
Forfait forfait = new Forfait()
{
Data = "data",
Id = 99
};
Act act = new Act()
{
Entity = JObject.FromObject(forfait)
};
await client.Indices.CreateAsync("index", o => o
.Map<Act>(m => m
.AutoMap()
2.Use DynamicTemplates but i can't find SearchAsYouType in the Mapping, it seems that it doesn't exist in Nest 7.4.1 yet
await client.Indices.CreateAsync("index", o => o
.Map<Act>(m => m
.DynamicTemplates(d =>d
.DynamicTemplate("stringassearch",dt => dt
.Match("entity.*")
.MatchMappingType("string")
.Mapping(ma =>ma
.)))));
3.Use a Visitor to force every String to be a SearchAsYouType
public class EveryStringIsASearchAsYouTypePropertyVisitor : NoopPropertyVisitor
{
public override IProperty Visit(PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute)
{
if (propertyInfo.PropertyType == typeof(String))
return new SearchAsYouTypeProperty();
return null;
}
}
await client.Indices.CreateAsync("index", o => o
.Map<Act>(m => m
.AutoMap(new EveryStringIsASearchAsYouTypePropertyVisitor(),2)
Everything failed
I have a feeling the solution is in the NEST.JsonNetSerializer to somehow make the settings used in the mapping apply inside the JObject but i couldn't find anything useful
2.Use DynamicTemplates but i can't find SearchAsYouType in the Mapping, it seems that it doesn't exist in Nest 7.4.1 yet
You are right, looks like it's missing from SingleMappingSelector
, but you can easily work around it with this extension class which will add support for search_as_you_type
type.
static class MappingExtension
{
public static IProperty SearchAsYouType<T>(this SingleMappingSelector<T> mappingSelector,
Func<SearchAsYouTypePropertyDescriptor<T>, ISearchAsYouTypeProperty> selector) where T : class
=> selector?.Invoke(new SearchAsYouTypePropertyDescriptor<T>());
}
and then you can create your dynamic template like follow
var createIndexResponse = await client.Indices.CreateAsync("index", o => o
.Map<Act>(m => m
.AutoMap<Act>()
.DynamicTemplates(d => d
.DynamicTemplate("stringassearch", dt => dt
.PathMatch("entity.*")
.MatchMappingType("string")
.Mapping(ma => ma.SearchAsYouType(s => s))))));
Note, I have changed Match(..)
to PathMatch(..)
- I think this is what you need. Also, I had to change Act
definition to
public class Act
{
public object Entity;
}
After indexing sample document this index mapping was created
{
"index": {
"mappings": {
"dynamic_templates": [
{
"stringassearch": {
"path_match": "entity.*",
"match_mapping_type": "string",
"mapping": {
"type": "search_as_you_type"
}
}
}
],
"properties": {
"entity": {
"properties": {
"data": {
"type": "search_as_you_type",
"max_shingle_size": 3
},
"id": {
"type": "long"
}
}
}
}
}
}
}
Here is the GH issue.
Hope that helps.