.Net Core中使用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.5StickySniffingConnectionPool黏性嗅探連線池
選擇一個可用節點作為請求主節點,支援ping 支援嗅探
二、注入
官方推薦使用單例注入ElasticClient。
services.AddSingleton<IElasticClient>(provider => { var connectionPool = new SingleNodeConnectionPool(new Uri("http://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 表示是否更新成功。
封裝裝一個操作倉儲,連結