如何使用Elastic.Clients.Elasticsearch C#定义父子关系
使用Elastic.Clients.Elasticsearch实现父子文档关系
一、改造实体类
适配新客户端库的实体类定义如下,核心是替换命名空间并使用新的JoinField类型:
using Elastic.Clients.Elasticsearch.Attributes; using Elastic.Clients.Elasticsearch.Mapping; public abstract class BaseDocument { public virtual int Id { get; set; } public int ParentId { get; set; } // 新客户端的Join字段类型 public JoinField JoinField { get; set; } public BaseDocument() { } } [ElasticsearchType(RelationName = "product")] public class Product : BaseDocument { [Keyword] public string Name { get; set; } public decimal Price { get; set; } } [ElasticsearchType(RelationName = "stock")] public class Stock : BaseDocument { [Keyword] public string Country { get; set; } public int Quantity { get; set; } } [ElasticsearchType(RelationName = "supplier")] public class Supplier : BaseDocument { [Keyword] public string SupplierDescription { get; set; } } [ElasticsearchType(RelationName = "category")] public class Category : BaseDocument { [Keyword] public string CategoryDescription { get; set; } }
二、创建索引并定义父子映射
以下是对应原NEST代码的索引创建实现,适配新客户端的API语法:
var createIndexResponse = _elasticClient.Indices.Create(_indexName, c => c .Settings(s => s .NumberOfReplicas(0) .RefreshInterval(-1) .NumberOfShards(5)) .Map<BaseDocument>(m => m .RoutingField(r => r.Required(true)) // 强制路由,确保父子文档存储在同一分片 .AutoMap<Product>() .AutoMap<Category>() .AutoMap<Supplier>() .AutoMap<Stock>() // 手动配置Product的Name字段(对应原代码的Text类型定义) .Properties(props => props .Text(t => t .Name(p => p.Name) .Analyzer("default") .Fields(f => f.Keyword(k => k.Name("keyword")))) // 定义父子关系映射 .Join(j => j .Name(p => p.JoinField) .Relations(r => r // 指定Product为父类型,关联category、supplier、stock三个子类型 .Add<Product>(childRelations => childRelations .Children("category", "supplier", "stock"))))));
三、父子文档写入示例
写入父文档(Product)
var product = new Product { Id = 1, Name = "Sample Phone", Price = 2999.99m, JoinField = JoinField.Create<Product>() // 标记为父文档类型 }; var indexProductResponse = _elasticClient.Index(product, i => i .Routing(product.Id.ToString()) .Index(_indexName));
写入子文档(Stock)
var stock = new Stock { Id = 1001, ParentId = 1, Country = "CN", Quantity = 100, JoinField = JoinField.LinkTo<Product>(1) // 指定关联的父文档ID和类型 }; var indexStockResponse = _elasticClient.Index(stock, i => i .Routing(stock.ParentId.ToString()) // 路由值必须与父文档一致 .Index(_indexName));
关键注意事项
- 父子文档必须使用相同的路由值(通常用父文档ID),否则无法建立关联,开启
RoutingField.Required(true)可以强制校验这一点。 - 子类型名称必须与实体类
[ElasticsearchType(RelationName)]指定的名称完全匹配。 - 新客户端的
JoinField提供了Create<TParent>和LinkTo<TParent>(parentId)两个便捷方法,分别用于创建父文档和子文档的关联字段值。
内容的提问来源于stack exchange,提问作者user2932893
相关产品推荐
相关产品推荐

