.netcore 简单使用ElasticSearch


.netcore 简单使用ElasticSearch(7.6)

最近在捣鼓学习了下ElasticSearch,在此记录下使用.netcore操作elastic search 的实现(简单的封装,使用)。需要注意的是不同版本的Elastic Search差异可能较大,需要对应版本去封装操作,例如6.x版本的支持1个index下多个Type,而7.x已经开始去掉了type概念,而且查询等操作中必须先指明indexname,否则报错。

项目需要添加Elasticsearch.NetNest

相关文档地址

Elasticsearch文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html

Elasticsearch.Net和Nest官方文档:https://www.elastic.co/guide/en/elasticsearch/client/net-api/7.x/index.html

1、封装ElasticClient提供者

1)创建ElasticSearch配置类

1  public class EsConfig : IOptions
2     {
3         public List<string> Urls { get; set; }
4 
5         public EsConfig Value => this;
6     }

2)创建ElasticSearch提供者接口以及类

 1     /// 
 2     /// ElasticClient 提供者接口
 3     /// 
 4     public interface IEsClientProvider
 5     {
 6         /// 
 7         /// 获取ElasticClient
 8         /// 
 9         ///  
10         ElasticClient GetClient();
11         /// 
12         /// 指定index获取ElasticClient
13         /// 
14         /// 
15         /// 
16         ElasticClient GetClient(string indexName);
17     }
18 
19 
20 
21     /// 
22     /// ElasticClient提供者
23     /// 
24     public class EsClientProvider : IEsClientProvider
25     {
26         private readonly IOptions _EsConfig;
27         public EsClientProvider(IOptions esConfig)
28         {
29             _EsConfig = esConfig;
30         }
31         /// 
32         /// 获取elastic client  
33         /// 
34         ///  
35         public ElasticClient GetClient()
36         {
37             if (_EsConfig == null || _EsConfig.Value == null || _EsConfig.Value.Urls == null || _EsConfig.Value.Urls.Count < 1)
38             {
39                 throw new Exception("urls can not be null");
40             }
41             return GetClient(_EsConfig.Value.Urls.ToArray(), "");
42         }
43         /// 
44         /// 指定index获取ElasticClient
45         /// 
46         /// 
47         /// 
48         public ElasticClient GetClient(string indexName)
49         {
50             if (_EsConfig == null || _EsConfig.Value == null || _EsConfig.Value.Urls == null || _EsConfig.Value.Urls.Count < 1)
51             {
52                 throw new Exception("urls can not be null");
53             }
54             return GetClient(_EsConfig.Value.Urls.ToArray(), indexName);
55         }
56 
57 
58         /// 
59         /// 根据url获取ElasticClient
60         /// 
61         /// 
62         /// 
63         /// 
64         private ElasticClient GetClient(string url, string defaultIndex = "")
65         {
66             if (string.IsNullOrWhiteSpace(url))
67             {
68                 throw new Exception("es 地址不可为空");
69             }
70             var uri = new Uri(url);
71             var connectionSetting = new ConnectionSettings(uri);
72             if (!string.IsNullOrWhiteSpace(url))
73             {
74                 connectionSetting.DefaultIndex(defaultIndex);
75             }
76             return new ElasticClient(connectionSetting);
77         }
78         /// 
79         /// 根据urls获取ElasticClient
80         /// 
81         /// 
82         /// 
83         /// 
84         private ElasticClient GetClient(string[] urls, string defaultIndex = "")
85         {
86             if (urls == null || urls.Length < 1)
87             {
88                 throw new Exception("urls can not be null");
89             }
90             var uris = urls.Select(p => new Uri(p)).ToArray();
91             var connectionPool = new SniffingConnectionPool(uris);
92             var connectionSetting = new ConnectionSettings(connectionPool);
93             if (!string.IsNullOrWhiteSpace(defaultIndex))
94             {
95                 connectionSetting.DefaultIndex(defaultIndex);
96             }
97             return new ElasticClient(connectionSetting);
98         }
99     }

---------用户密码验证(注释部分),可以配置在EsConfig中---------

 1  /// 
 2         /// 根据urls获取ElasticClient
 3         /// 
 4         /// 
 5         /// 
 6         /// 
 7         public ElasticClient GetClient(string[] urls, string defaultIndex = "")
 8         {
 9             if (urls == null || urls.Length < 1)
10             {
11                 throw new Exception("urls can not be null");
12             }
13             var uris = urls.Select(p => new Uri(p)).ToArray();
14             var connectionPool = new SniffingConnectionPool(uris);
15             var connectionSetting = new ConnectionSettings(connectionPool);
16             if (!string.IsNullOrWhiteSpace(defaultIndex))
17             {
18                 connectionSetting.DefaultIndex(defaultIndex);
19             }
20             //connectionSetting.BasicAuthentication("", ""); //设置账号密码
21             return new ElasticClient(connectionSetting);
22         }

---------------------

2、封装操作ElasticSearch实现

1)、扩展ElasticClient类

 1     /// 
 2     /// ElasticClient 扩展类
 3     /// 
 4     public static class ElasticClientExtension
 5     {
 6         /// 
 7         /// 创建索引
 8         /// 
 9         /// 
10         /// 
11         /// 
12         /// 
13         /// 
14         /// 
15         public static bool CreateIndex(this ElasticClient elasticClient, string indexName = "", int numberOfShards = 5, int numberOfReplicas = 1) where T : class
16         {
17             
18             if (string.IsNullOrWhiteSpace(indexName))
19             {
20                 indexName = typeof(T).Name;
21             }
22              
23             if (elasticClient.Indices.Exists(indexName).Exists)
24             {
25                 return false;
26             }
27             else
28             {
29                 var indexState = new IndexState()
30                 {
31                     Settings = new IndexSettings()
32                     {
33                         NumberOfReplicas = numberOfReplicas,
34                         NumberOfShards = numberOfShards,
35                     },
36                 };
37                 var response = elasticClient.Indices.Create(indexName, p => p.InitializeUsing(indexState).Map(p => p.AutoMap()));
38                 return response.Acknowledged;
39             }
40         }
41     }

2)、创建ElasticSearch操作基类

 1     /// 
 2     /// 接口限定
 3     /// 
 4     public interface IBaseEsContext { }
 5     /// 
 6     /// es操作基类
 7     /// 
 8     /// 
 9     public abstract class BaseEsContext : IBaseEsContext where T : class
10     {
11         protected IEsClientProvider _EsClientProvider;
12         public abstract string IndexName { get;  }
13         public BaseEsContext(IEsClientProvider provider)
14         {
15             _EsClientProvider = provider;
16         }
17 
18         /// 
19         /// 批量更新
20         /// 
21         /// 
22         /// 
23         public bool InsertMany(List tList)
24         {
25             var client = _EsClientProvider.GetClient(IndexName);
26             if (!client.Indices.Exists(IndexName).Exists)
27             {
28                 client.CreateIndex(IndexName);
29             }
30             var response = client.IndexMany(tList);
31             //var response = client.Bulk(p=>p.Index(IndexName).IndexMany(tList));
32             return response.IsValid;
33         }
34 
35         /// 
36         /// 获取总数
37         /// 
38         /// 
39         public long GetTotalCount()
40         {
41             var client = _EsClientProvider.GetClient(IndexName);
42             var search = new SearchDescriptor().MatchAll(); //指定查询字段 .Source(p => p.Includes(x => x.Field("Id")));
43             var response = client.Search(search);
44             return response.Total;
45         }
46         /// 
47         /// 根据Id删除数据
48         /// 
49         /// 
50         public bool DeleteById(string id)
51         {
52             var client = _EsClientProvider.GetClient(IndexName);
53             var response = client.Delete(id);
54             return response.IsValid;
55         }
56 
57     }

3)、具体操作类(示例)

 1     /// 
 2     /// 地址操作类
 3     /// 
 4     public class AddressContext : BaseEsContext
5 { 6 /// 7 /// 索引名称 8 /// 9 public override string IndexName => "address"; 10 public AddressContext(IEsClientProvider provider) : base(provider) 11 { 12 } 13 /// 14 /// 获取地址 15 /// 16 /// 17 /// 18 /// 19 /// 20 public List
GetAddresses(string province, int pageIndex, int pageSize) 21 { 22 var client = _EsClientProvider.GetClient(IndexName); 23 var musts = new List, QueryContainer>>(); 24 musts.Add(p => p.Term(m => m.Field(x=>x.Pronvince).Value(province))); 25 var search = new SearchDescriptor
(); 26 // search = search.Index(IndexName).Query(p => p.Bool(m => m.Must(musts))).From((pageIndex - 1) * pageSize).Take(pageSize); 27 search =search.Query(p => p.Bool(m => m.Must(musts))).From((pageIndex - 1) * pageSize).Take(pageSize); 28 var response = client.Search
(search); 29 return response.Documents.ToList(); 30 } 31 /// 32 /// 获取所有地址 33 /// 34 /// 35 public List
GetAllAddresses() 36 { 37 var client = _EsClientProvider.GetClient(IndexName); 38 var searchDescriptor = new SearchDescriptor
(); 39 // searchDescriptor = searchDescriptor.Index(IndexName).Query(p => p.MatchAll()); 40 searchDescriptor = searchDescriptor.Query(p => p.MatchAll()); 41 var response = client.Search
(searchDescriptor); 42 return response.Documents.ToList(); 43 } 44 /// 45 /// 删除指定城市的数据 46 /// 47 /// 48 /// 49 public bool DeleteByQuery(string city) 50 { 51 var client = _EsClientProvider.GetClient(IndexName); 52 var musts = new List, QueryContainer>>(); 53 musts.Add(p=>p.Term(m=>m.Field(f=>f.City).Value(city))); 54 var search = new DeleteByQueryDescriptor
().Index(IndexName); 55 search = search.Query(p => p.Bool(m => m.Must(musts))); 56 var response = client.DeleteByQuery
(p=>search); 57 return response.IsValid; 58 } 59 60 }

 address类

 1     [ElasticsearchType(IdProperty = "Id")]
 2     public class Address
 3     {
 4         [Keyword]
 5         public string Id { get; set; }
 6         [Keyword]
 7         public string Country { get; set; }
 8         [Keyword]
 9         public string City { get; set; }
10         [Keyword]
11         public string Pronvince { get; set; }
12         [Keyword]
13         public string Area { get; set; }
14         [Text]
15         public string Address1 { get; set; }
16 
17     }

3、项目中注入和使用ElasticSearch

1)、配置文件

1   "EsConfig": {
2     "ConnectionStrings": [ "http://127.0.0.1:9200/" ] 
3   }

2)、注入ElasticSearch

 1    services.Configure(options =>
 2           {
 3               options.Urls = Configuration.GetSection("EsConfig:ConnectionStrings").GetChildren().ToList().Select(p => p.Value).ToList();
 4 
 5           });
 6 
 7 
 8             services.AddSingleton();
 9             var types = Assembly.Load("John.DotNetCoreStudy.EsCommon").GetTypes().Where(p => !p.IsAbstract && (p.GetInterfaces().Any(i => i == typeof(IBaseEsContext)))).ToList();
10             types.ForEach(p =>
11                     services.AddTransient(p)
12                 );

3)、Controller类中使用

 1     [Route("api/[controller]")]
 2     [ApiController]
 3     public class AddressController : ControllerBase
 4     {
 5         private AddressContext _AddressContext;
 6         public AddressController(AddressContext context)
 7         {
 8             _AddressContext = context;
 9         }
10         /// 
11         /// 新增或者修改
12         /// 
13         /// 
14         [HttpPost("添加地址")]
15         public void AddAddress(List
addressList) 16 { 17 if (addressList == null || addressList.Count < 1) 18 { 19 return; 20 } 21 _AddressContext.InsertMany(addressList); 22 } 23 24 /// 25 /// 删除地址 26 /// 27 /// 28 [HttpPost("deleteAddress")] 29 public void DeleteAdress(string id) 30 { 31 _AddressContext.DeleteById(id); 32 } 33 /// 34 /// 获取所有与地址 35 /// 36 /// 37 [HttpGet("getAllAddress")] 38 public List
GetAllAddress() 39 { 40 return _AddressContext.GetAllAddresses(); 41 } 42 /// 43 /// 获取地址总数 44 /// 45 /// 46 [HttpGet("getAddressTotalCount")] 47 public long GetAddressTotalCount() 48 { 49 return _AddressContext.GetTotalCount(); 50 } 51 52 /// 53 /// 分页获取(可以进一步封装查询条件) 54 /// 55 /// 56 /// 57 /// 58 /// 59 [HttpPost("getAddressByProvince")] 60 public List
GetAddressByProvince(string province,int pageIndex,int pageSize) 61 { 62 return _AddressContext.GetAddresses(province,pageIndex,pageSize); 63 } 64 65 }

4、测试(略)

 

 

-------------------------------------

以上

当然es还有很多操作的,聚合查询、不同条件的查询(范围查询、匹配查询等等)、分词等。具体可以去查看其官方文档对应实现!