.Net Core中使用ElasticSearch(二)
- 2021 年 11 月 27 日
- 筆記
- elasticsearch
.Net的ElasticSearch 有兩個版本,Elasticsearch.Net(低級) 和 NEST(高級),推薦使用 NEST,低級版本的更靈活,水太深 把握不住。有個需要注意,使用的版本號必須要ElasticSearch服務端版本號一致。
一、 連接池
1.1 SingleNodeConnectionPool 單節點連接池
適合只有一個節點的情況。當沒有在ConnectionSettings 構造函數中顯式指定連接池類型的時候,默認此連接池。這種連接池不會標記節點是否存活
1.2 StaticConnectionPool 靜態連接池
適合多個節點,它維護一個靜態的節點hosts清單,使用前通過ping節點來確認節點是否存活。如果一個節點處理請求失敗,該節點會被標記為死節點,這個節點會被「關禁閉」,「關禁閉」出來後,會再次處理請求,如果還是失敗,「關禁閉」的時間會更長。
1.3 SniffingConnectionPool 嗅探連接池
它繼承至靜態連接池,有靜態連接池的Ping特性。區別在於是動態的,用戶提供hosts種子,而客戶端則會嗅探這些hosts並發現集群的其他節點。當集群中添加或刪除節點時,客戶端會相應更新。
1.4 StickyConnectionPool 黏性連接池
選擇一個可用節點作為請求主節點,支持ping 不支持嗅探
1.5 StickySniffingConnectionPool 黏性嗅探連接池
選擇一個可用節點作為請求主節點,支持ping 支持嗅探
二、注入
官方推薦使用單例注入ElasticClient。
services.AddSingleton<IElasticClient>(provider => { var connectionPool = new SingleNodeConnectionPool(new Uri("//127.0.0.1:9200")); var connectionSetting = new ConnectionSettings(connectionPool).DisableDirectStreaming(); return new ElasticClient(connectionSetting); });
三、增刪改查
3.1 添加
3.1.1 單個添加
var user = new User() { Id = 1, Age = 18, Name = "MicroHeart", Gender = true }; //第一種
var resp = client.Index(user, s => s.Index(indexName));//指定操作索引名稱 //第二種 connectionSettings.DefaultIndex(indexName);//指定默認索引名稱 var client = new ElasticClient(connectionSettings); resp = client.IndexDocument(user);//操作默認索引
3.1.2 批量添加
//第一種 var resp = client.IndexMany(new List<User>() { user }); //操作默認索引 resp = client.IndexMany(new List<User>() { user }, indexName); //操作指定索引 //第二種 resp = client.Bulk(b => b.Index(indexName).IndexMany(users, (desc, user) => desc.Index(user.Gender ? "boy" : "girl"))); //第三種 var bulkAllObservable = client.BulkAll(users, b => b .Index("people") .BackOffTime("30s") //重試間隔時間 .BackOffRetries(2) //重試次數 .RefreshOnCompleted() .MaxDegreeOfParallelism(Environment.ProcessorCount) .Size(1000) //每次請求文檔個數 );
IndexMany:是在單個 HTTP 請求所有文檔,因此對於非常大的文檔集合,這不是建議的方法。
Bulk:是在單個 HTTP 請求所有文檔,如果需要對很多文檔進行索引控制,可以使用此方法。例子中將男孩插入「boy」索引中,女孩添加到「girl」索引中
BulkAll:適合對多個大文檔集合操作,在多個HTTP請求中,分批次操作文檔,內置了重試機制。
上面所有的插入方法都是根據_id的值判斷文檔是否存在(這裡因為user有個屬性為Id,默認Es將Id的屬性值作為_id的值),如果已經存在文檔,就更新,否則就添加。
通過返回對象的IsValid屬性來判斷是否添加成功。
3.2 刪除
var resp = client.Delete<User>(1, d => d.Index(indexName));//單個刪除 var resp = client.DeleteByQuery<User>(x => x.Index(indexName).Query(q => q.Range(r => r.Field(f => f.Age).LessThan(18)))); //刪除年齡小於18的
返回的對象包含
deleted:表示刪除的數量。
Failures:刪除失敗的集合。
3.3 查詢
3.3.1 根據Id獲取單個
var resp = client.Get<User>(3, d => d.Index(indexName));
返回的類型為 GetResponse<User>,包含下面幾個屬性。
index:表示索引,
type:值固定為「_doc」,
found:表示是否找到文檔,
version:文檔的版本號,
source:存儲的數據user
3.3.2 根據Id集合獲取多個
var resp = client.GetMany<User>(new List<long>() { 19L, 20L, 21L }, indexName);
3.3.3 根據條件查詢
var resp = client.Search<User>(x => x.Index(indexName) .From(0) .Size(20) .Query(q => q.Range(r => r.Field(f => f.Age).GreaterThan(18)) && q.Range(r => r.Field(f => f.Age).LessThan(30)) && q.Term(t => t.Gender, true)));
返回的類型為 ISearchResponse<User>,包含下面幾個屬性。
TimedOut:查詢是否超時
Shards:完成這個搜索查詢了多少個分片
Took:此次查詢消耗的時間
MaxScore:此次查詢中最符合查詢條件的文檔的最大得分
Total:符合查詢條件的總數
Hits:存儲的數據user集合
例子只是簡單的查詢。ES專為查詢而生,所以它的查詢很靈活,後面單獨講。
3.4 更新
var user = new User() { Age = 18, Gender = false, Name = "test" }; var resp4 = client.Update<User>(20, u => u.Index(indexName).Doc(user));
返回的IsValid 表示是否更新成功。
封裝裝一個操作倉儲,鏈接