elasticsearch,nest,C#,elasticsearch,Nest" /> elasticsearch,nest,C#,elasticsearch,Nest" />

C# 使用NEST 2.x的多字段映射语法创建索引

C# 使用NEST 2.x的多字段映射语法创建索引,c#,elasticsearch,nest,C#,elasticsearch,Nest,我似乎无法获得NEST 2.0中多字段映射的正确语法——如果这是正确的术语的话。我发现的每个映射示例似乎都是我认为您至少有两种可能来解决您的问题: 关于索引:创建类似元数据模型的东西,它存储起来只是为了检索。请参阅以限制返回此字段 搜索时:指定要查询的字段:如果不想查询CreatedDate,就不要将其包含在搜索中 在我的例子中,我使用这两种方法来获得非常快的结果:-)据我所见,您没有任何尝试映射的复杂类型。因此,您可以轻松地使用嵌套属性映射对象 看看这个: [Nest.Elasticsearc

我似乎无法获得NEST 2.0中多字段映射的正确语法——如果这是正确的术语的话。我发现的每个映射示例似乎都是我认为您至少有两种可能来解决您的问题:

  • 关于索引:创建类似元数据模型的东西,它存储起来只是为了检索。请参阅以限制返回此字段
  • 搜索时:指定要查询的字段:如果不想查询CreatedDate,就不要将其包含在搜索中

  • 在我的例子中,我使用这两种方法来获得非常快的结果:-)

    据我所见,您没有任何尝试映射的复杂类型。因此,您可以轻松地使用嵌套属性映射对象

    看看这个:

    [Nest.ElasticsearchType]
    public class MyType
    {
        // Index this & allow for retrieval.
        [Nest.Number(Store=true)]
        int Id { get; set; }
    
        // Index this & allow for retrieval.
        // **Also**, in my searching & sorting, I need to sort on this **entire** field, not just individual tokens.
        [Nest.String(Store = true, Index=Nest.FieldIndexOption.Analyzed, TermVector=Nest.TermVectorOption.WithPositionsOffsets)]
        string CompanyName { get; set; }
    
        // Don't index this for searching, but do store for display.
        [Nest.Date(Store=true, Index=Nest.NonStringIndexOption.No)]
        DateTime CreatedDate { get; set; }
    
        // Index this for searching BUT NOT for retrieval/displaying.
        [Nest.String(Store=false, Index=Nest.FieldIndexOption.Analyzed)]
        string CompanyDescription { get; set; }
    
        [Nest.Nested(Store=true, IncludeInAll=true)]
        // Nest this.
        List<MyChildType> Locations { get; set; }
    }
    
    [Nest.ElasticsearchType]
    public class MyChildType
    {
        // Index this & allow for retrieval.
        [Nest.String(Store=true, Index = Nest.FieldIndexOption.Analyzed)]
        string LocationName { get; set; }
    
        // etc. other properties.
    }
    
    [Nest.ElasticsearchType]
    公共类MyType
    {
    //索引此项并允许检索。
    [Nest.Number(Store=true)]
    int Id{get;set;}
    //索引此项并允许检索。
    //**另外**,在我的搜索和排序中,我需要对**整个**字段进行排序,而不仅仅是单个令牌。
    [Nest.String(Store=true,Index=Nest.FieldIndexOption.analysed,TermVector=Nest.TermVectorOption.WithPositionsOffset)]
    字符串CompanyName{get;set;}
    //不要为此索引进行搜索,但要存储以供显示。
    [Nest.Date(Store=true,Index=Nest.NonStringIndexOption.No)]
    DateTime CreatedDate{get;set;}
    //将此索引用于搜索,但不用于检索/显示。
    [Nest.String(Store=false,Index=Nest.FieldIndexOption.Analyzed)]
    字符串公司说明{get;set;}
    [Nest.Nested(Store=true,includenall=true)]
    //嵌套这个。
    列出位置{get;set;}
    }
    [嵌套.弹性搜索类型]
    公共类MyChildType
    {
    //索引此项并允许检索。
    [Nest.String(Store=true,Index=Nest.FieldIndexOption.Analyzed)]
    字符串位置名称{get;set;}
    //等其他属性。
    }
    
    在此声明之后,要在elasticsearch中创建此映射,您需要进行如下调用:

    var mappingResponse = elasticClient.Map<MyType>(m => m.AutoMap());
    
    var-mappingResponse=elasticClient.Map(m=>m.AutoMap());
    
    通过AutoMap()调用,NEST将从POCO读取属性,并相应地创建映射请求

    另请参见中的“基于属性的映射”部分


    干杯

    在撰写本文时,Nest没有提供使用内置属性将类中的属性映射到文档映射中的多个字段的方法。但是,它确实提供了对映射执行任何操作所需的工具,如果您自己编写JSON,则可以执行这些操作

    这是一个我为自己的需要而制定的解决方案。把它作为你需要做的任何事情的起点应该不难

    首先,这里有一个我想要生成的映射示例

    {
       "product":{
          "properties":{
             "name":{
                "type":"string",
                "index":"not_analyzed",
                "fields":{
                   "standard":{
                      "type":"string",
                      "analyzer":"standard"
                   }
                }
             }
          }
       }
    }
    
    产品
    文档将有
    名称
    字段,该字段已编制索引但未进行分析,以及
    名称.standard
    字段,该字段使用标准分析器

    我从中生成映射的C#类如下所示

    [ElasticsearchType]
    public class Product
    {
        [WantsStandardAnalysisField]
        public string Name { get; set; }
    }
    
    注意
    WantsStandardAnalysisField
    属性。这是一个自定义属性,没有添加特殊属性。字面上只是:

    public class WantsStandardAnalysisField : Attribute {}
    
    如果我按原样使用AutoMap,我的自定义属性将被忽略,并且我将得到一个具有
    name
    字段的映射,但不具有
    name.standard
    。幸运的是,AutoMap接受了
    IPropertyVisitor
    的一个实例。名为
    NoopPropertyVisitor
    的基类实现该接口,但什么也不做,因此您可以对其进行子类化,只覆盖您关心的方法。当您将属性访问者与AutoMap一起使用时,它将为您生成文档映射,但在将其发送到Elastic Search之前,您有机会对其进行修改。我们所需要做的就是查找用自定义属性标记的属性,并为它们添加一个字段

    下面是一个这样做的示例:

    public class ProductPropertyVisitor : NoopPropertyVisitor
    {
        public override void Visit(IStringProperty type, PropertyInfo propertyInfo, ElasticsearchPropertyAttributeBase attribute)
        {
            base.Visit(type, propertyInfo, attribute);
    
            var wsaf = propertyInfo.GetCustomAttribute<WantsStandardAnalysisField>();
            if (wsaf != null)
            {
                type.Index = FieldIndexOption.NotAnalyzed;
                type.Fields = new Properties
                {
                    {
                        "standard",
                        new StringProperty
                        {
                            Index = FieldIndexOption.Analyzed,
                            Analyzer = "standard"
                        }
                    }
                };
            }
        }
    }
    
    公共类ProductPropertyVisitor:NoopPropertyVisitor
    {
    公共覆盖无效访问(IStringProperty类型、PropertyInfo PropertyInfo、ElasticsearchPropertyAttributeBase属性)
    {
    base.Visit(类型、属性信息、属性);
    var wsaf=propertyInfo.GetCustomAttribute();
    if(wsaf!=null)
    {
    type.Index=FieldIndexOption.notanalysis;
    type.Fields=新属性
    {
    {
    “标准”,
    新StringProperty
    {
    索引=字段索引选项。已分析,
    Analyzer=“标准”
    }
    }
    };
    }
    }
    }
    
    正如您所看到的,我们可以对生成的属性执行几乎任何我们想要的操作,包括关闭主属性的分析,并添加具有自己设置的新字段。为了好玩,您可以向自定义属性添加几个属性,允许您指定所需字段的名称和要使用的分析器。您甚至可以修改代码以查看该属性是否已被添加多次,从而可以根据需要添加任意多的字段

    如果要通过使用AutoMap生成映射的任何方法运行此操作,例如:

    new TypeMappingDescriptor<Product>().AutoMap(new ProductPropertyVisitor())
    
    new TypeMappingDescriptor().AutoMap(new ProductPropertyVisitor())
    
    您将获得所需的多字段映射。现在,您可以自定义映射到您内心的内容。享受吧

    除了和答案,您还可以通过fluent(和对象初始值设定项语法)映射API完全控制映射。下面是一个基于您的需求的示例

    void Main()
    {
        var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
        var connectionSettings = new ConnectionSettings(pool);
    
        var client = new ElasticClient(connectionSettings);
    
        client.Map<MyType>(m => m
            .Index("index-name")
            .AutoMap()
            .Properties(p => p
                .String(s => s
                    .Name(n => n.CompanyName)
                    .Fields(f => f
                        .String(ss => ss
                            .Name("raw")
                            .NotAnalyzed()
                        )
                    )
                )
                .Date(d => d
                    .Name(n => n.CreatedDate)
                    .Index(NonStringIndexOption.No)         
                )
                .String(s => s
                    .Name(n => n.CompanyDescription)
                    .Store(false)
                )
                .Nested<MyChildType>(n => n
                    .Name(nn => nn.Locations.First())
                    .AutoMap()
                    .Properties(pp => pp
                        /* properties of MyChildType */
                    )
                )
            )
        );
    }
    
    public class MyType
    {
        // Index this & allow for retrieval.
        public int Id { get; set; }
    
        // Index this & allow for retrieval.
        // **Also**, in my searching & sorting, I need to sort on this **entire** field, not just individual tokens.
        public string CompanyName { get; set; }
    
        // Don't index this for searching, but do store for display.
        public DateTime CreatedDate { get; set; }
    
        // Index this for searching BUT NOT for retrieval/displaying.
        public string CompanyDescription { get; set; }
    
        // Nest this.
        public List<MyChildType> Locations { get; set; }
    }
    
    public class MyChildType
    {
        // Index this & allow for retrieval.
        public string LocationName { get; set; }
    
        // etc. other properties.
    }
    
    调用
    .AutoMap()
    会导致NEST根据属性类型和应用于属性的任何属性推断映射。然后
    .Properties()
    覆盖任何推断的映射。比如说

    • CompanyName
      被映射为带有fi的
      multi\u字段
      
      new TypeMappingDescriptor<Product>().AutoMap(new ProductPropertyVisitor())
      
      void Main()
      {
          var pool = new SingleNodeConnectionPool(new Uri("http://localhost:9200"));
          var connectionSettings = new ConnectionSettings(pool);
      
          var client = new ElasticClient(connectionSettings);
      
          client.Map<MyType>(m => m
              .Index("index-name")
              .AutoMap()
              .Properties(p => p
                  .String(s => s
                      .Name(n => n.CompanyName)
                      .Fields(f => f
                          .String(ss => ss
                              .Name("raw")
                              .NotAnalyzed()
                          )
                      )
                  )
                  .Date(d => d
                      .Name(n => n.CreatedDate)
                      .Index(NonStringIndexOption.No)         
                  )
                  .String(s => s
                      .Name(n => n.CompanyDescription)
                      .Store(false)
                  )
                  .Nested<MyChildType>(n => n
                      .Name(nn => nn.Locations.First())
                      .AutoMap()
                      .Properties(pp => pp
                          /* properties of MyChildType */
                      )
                  )
              )
          );
      }
      
      public class MyType
      {
          // Index this & allow for retrieval.
          public int Id { get; set; }
      
          // Index this & allow for retrieval.
          // **Also**, in my searching & sorting, I need to sort on this **entire** field, not just individual tokens.
          public string CompanyName { get; set; }
      
          // Don't index this for searching, but do store for display.
          public DateTime CreatedDate { get; set; }
      
          // Index this for searching BUT NOT for retrieval/displaying.
          public string CompanyDescription { get; set; }
      
          // Nest this.
          public List<MyChildType> Locations { get; set; }
      }
      
      public class MyChildType
      {
          // Index this & allow for retrieval.
          public string LocationName { get; set; }
      
          // etc. other properties.
      }
      
      {
        "properties": {
          "id": {
            "type": "integer"
          },
          "companyName": {
            "type": "string",
            "fields": {
              "raw": {
                "type": "string",
                "index": "not_analyzed"
              }
            }
          },
          "createdDate": {
            "type": "date",
            "index": "no"
          },
          "companyDescription": {
            "type": "string",
            "store": false
          },
          "locations": {
            "type": "nested",
            "properties": {
              "locationName": {
                "type": "string"
              }
            }
          }
        }
      }