Search code examples
c#nestaws-elasticsearch

Unable to map Hashset<object> while creating elastic index using Nest c#


I am facing issues while creating index for my User model. My C# model is-

public sealed class User
{
     public long Id { get; set; }
     public string FullName { get; set; }
     public HashSet<Reference> References { get; set; }
}

public sealed class Reference
{
    public string Type { get; set; }
    public string Id { get; set; }
}

I am using NEST nuget for creating index.

var newIndexResponse = await _elasticClient.CreateIndexAsync(aliasData.NewIndex, i => i
                .Mappings(mappingsDescriptor => mappingsDescriptor
                    .Map<User>(m => m
                        .Properties(ps => ps
                            .Text(p => p
                                .Name(u => u.References)
                                .Analyzer(ElasticConstants.TwoLetterAnalyzerName)
                                .SearchAnalyzer(ElasticConstants.NameSearchAnalyzerName))
                            .Object<HashSet<Reference>>(p => p // This throws error
                                .Name(up => up.References)
                                .Properties(up => up.Object<Reference>(sp => sp
                                    .Properties(so => so
                                        .Keyword(eri => eri
                                            .Name(ei => ei.Id)))
                                    .Properties(so => so
                                        .Keyword(ert => ert.Name(t => t.Type)))
                                ))
                            )
                        )
    )));

When I try to run this code I am getting error for mapping Hashset.

Could not get field name for ObjectTypeDescriptor2 mapping: ArgumentException at Nest.PropertiesDescriptor1.SetProperty(IProperty type) at Nest.ObjectPropertyDescriptorBase4.<>c.<Properties>b__21_0(TInterface a, Func2 v) at Nest.Fluent.Assign[TDescriptor,TInterface,TValue](TDescriptor self, TValue value, Action`2 assign)

User model is a AWS DynamoDb entity so I am using Hashset in place of List. My end goal is to have search user by Type and Id in Reference class. I need help to figure out mapping of HashSet<Reference>.


Solution

  • I would rather use nested type instead of object for this case. That should help you with searching later on. You can read more about it here. NEST has a section in docs about configuring mapping you can check it as well.

    Here is a working example (tested with elasticsearch 6.2.4 and NEST 6.8.1)

    var newIndexResponse = await elasticClient.CreateIndexAsync("documents", i => i
        .Mappings(mappingsDescriptor => mappingsDescriptor
            .Map<User>(m => m
                .Properties(ps => ps
                    .Text(p => p
                        .Name(u => u.References))
                    .Nested<Reference>(p => p
                        .Name(up => up.References)
                        .Properties(sp => sp.Keyword(k => k.Name(n => n.Id)))
                        .Properties(sp => sp.Keyword(k => k.Name(n => n.Type)))
                    )
                )
            )));
    

    which creates an index with the following mapping in the elasticsearch

    {
      "documents": {
        "mappings": {
          "user": {
            "properties": {
              "references": {
                "type": "nested",
                "properties": {
                  "id": {
                    "type": "keyword"
                  },
                  "type": {
                    "type": "keyword"
                  }
                }
              }
            }
          }
        }
      }
    }
    

    Hope that helps.