创建索引模型:
#region 索引模型 [ElasticsearchType(Name = "product")] public class Product { [String(Store = true,Index=FieldIndexOption.No)] public string ProductName { get; set; } [String(Store = true, Index = FieldIndexOption.Analyzed)] public string BriefName { get; set; } [String(Store = true, Index = FieldIndexOption.NotAnalyzed)] public string ApplayRangetype { get; set; } [Date(Store = true, NumericResolution = NumericResolutionUnit.Seconds)] //Format = "MMddyyyy", public DateTime OnlineDateTime { get; set; } [Number(NumberType.Integer, Store = true)] public int ReviewCount { get; set; } [Number(NumberType.Float,Store = true)] public float Price { get; set; } } #endregion
索引模型和配置(批量导入数据时,可以考虑通过命令的方式先关闭复制和刷新,数据导入完成再开启)
/// <summary> /// 創建索引模型 /// </summary> public void Mapping() { var client = ElasticSearchCommon.GetInstance().GetElasticClient(); //往指定索引里面添加mapping、 //IPutMappingResponse r= client.Map<Product>(s => s.Index("shuaiproduct").AutoMap()); ICreateIndexRequest request=new CreateIndexDescriptor("shuaiproduct").Mappings(s=>s.Map<Product>(m=>m.AutoMap())); client.CreateIndex(request); }
/// <summary> /// 修改索引配置 /// </summary> /// <param name="indexName"></param> /// <param name="number_of_replicas">副本数 最小为0</param> /// <param name="refresh_interval">分片Refresh时间间隔 -1为不刷新 1s 代表每隔1s刷新一次</param> /// <returns></returns> public static IUpdateIndexSettingsResponse UpdateIndexSettings(string indexName, int number_of_replicas, string refresh_interval) { IUpdateIndexSettingsResponse response = null; try { var client = ESHelper.GetInstance().GetElasticClient(); response = client.UpdateIndexSettings(new UpdateIndexSettingsRequest(indexName) { //IndexSettings indexSettings=new IndexSettings (){ NumberOfReplicas=1, RefreshInterval=-1}; IndexSettings = new IndexSettings() { NumberOfReplicas = number_of_replicas, //副本数量 RefreshInterval = refresh_interval //分片Refresh时间间隔 } }); } catch (Exception ex) { } return response; } /// <summary> /// 对指定索引进行强制段合并 /// </summary> /// <param name="indexName"></param> /// <param name="maxNumSegments"></param> /// <returns></returns> public static IOptimizeResponse Optimize(string indexName, int maxNumSegments) { IOptimizeResponse response = null; try { var client = ESHelper.GetInstance().GetElasticClient(); response = client.Optimize(new OptimizeRequest() { MaxNumSegments = maxNumSegments }); } catch (Exception ex) { } return response; }
批量导入数据
/// <summary> /// 批量将对象导入es 是bulk命令的縮寫形式 /// 如果已存在就update 不存在就create /// </summary> public void IndexMany(List<Product> pros) { var client = ElasticSearchCommon.GetInstance().GetElasticClient(); var result = client.IndexMany<Product>(pros, "shuaiproduct", "product"); } /// <summary> /// 使用bulk命令 批量将对象导入es /// 如果已存在就update 不存在就create /// </summary> public void IndexBluk(List<Product> pros) { BulkDescriptor descriptor = new BulkDescriptor().Index("shuaiproduct").Type("product"); foreach (var p in pros) { descriptor.Index<Product>(s => s.Document(p)) .Routing(p.ApplayRangetype);//在导入数据的时候可以增加路由值,这样es会把相同路由值的文档分配到相同的分片上,搜索的时候指定路由值就可以直接在指定分片上搜索数据 } var client = ElasticSearchCommon.GetInstance().GetElasticClient(); client.Bulk(descriptor); //異步方法 //Task<IBulkResponse> br = client.BulkAsync(descriptor); //br.Wait(); }
根据条件删除索引中的文档:
/// <summary> /// 根據條件刪除索引 /// </summary> public void DeleteByQuery(string keyword) { var client = ElasticSearchCommon.GetInstance().GetElasticClient(); //1 模糊匹配 //var result= client.DeleteByQuery<Product>("shuaiproduct", "product", s => s.Query(r => r.Match(f=>f // .Field(fi=>fi.BriefName) // .Query(keyword)))); //2 精確匹配 //var resut = client.DeleteByQuery<Product>("shuaiproduct", "product", q => q.Query(s => s.Term(f => f.ReviewCount, keyword))); //3 多條件匹配 QueryContainer q1 = Query<Product>.Match(m => m.Field(f => f.BriefName).Query(keyword)); QueryContainer q2 = Query<Product>.Term(t => t.ApplayRangetype, "2"); QueryContainer q3 = Query<Product>.Term(t => t.Price, "11"); //刪除同時滿足這兩個條件的商品 //var resut = client.DeleteByQuery<Product>("shuaiproduct", "product", q => q.Query(s=>s.Bool(b=>b.Must(q1,q2)))); //排除條件匹配 刪除同時滿足q1 q2,不滿足q3的商品 // var resut = client.DeleteByQuery<Product>("shuaiproduct", "product", q => q.Query(s => s.Bool(b => b.Must(q1, q2).MustNot(q3)))); //範圍條件匹配 刪除價格區間在 大於11 小於等於20的商品 var resut = client.DeleteByQuery<Product>("shuaiproduct", "product", q => q.Query(s => s.Range(r=>r.Field(f=>f.Price).GreaterThan(11).LessThanOrEquals(20)))); }
根据条件执行修改:
http://es.xiaoleilu.com/030_Data/45_Partial_update.html
/// <summary> /// 根据条件修改部分字段 /// </summary> public void UpdateByScriptQuery() { var client = ElasticSearchCommon.GetInstance().GetElasticClient(); Func<UpdateByQueryDescriptor<Product>, IUpdateByQueryRequest> fun = f => f.Query(q => q.Term(t => t.Price, 11)).Script(s => s.Inline(string.Format("ctx._source.{0};ctx._source.{1}", "ReviewCount=200", "Price=111")));//ctx._source.ReviewCount=200;ctx._source.Price=111 也可以使用脚本参数parames var response = client.UpdateByQuery("shuaiproduct", "product", fun); } /// <summary> /// 根据id执行文档修改 /// </summary> public void UpdateByQuery() { var client = ElasticSearchCommon.GetInstance().GetElasticClient(); Product p = new Product() { ApplayRangetype="2", BriefName="如何形容女朋友胸小", Price=11, OnlineDateTime=DateTime.Now, ProductName="躺在床上感觉就像海尔兄弟", ReviewCount=100}; UpdateRequest<Product, Product> updateRequest = new UpdateRequest<Product, Product>("shuaiproduct", "product",1); var response =client.Update<Product>(updateRequest); }
查询:
public void Search(string keywords) { #region 构造查询条件,任何一个查询条件都可以单独执行查询 //0 前缀匹配Query<Product>.Prefix //1 精确匹配,全字匹配 QueryContainer q = Query<Product>.Term(t => t.ApplayRangetype, 2); //2 范围查询 QueryContainer drq = Query<Product>.DateRange(d => d.Field(f => f.OnlineDateTime).GreaterThan(DateMath.FromString("2016-10-01")).LessThanOrEquals(DateMath.Now));//注意日起位数不能少,2016-10-01 不能写成 2016-10-1 //3 单field模糊匹配 QueryContainer mq = Query<Product>.Match(m => m.Query(keywords).Field(f => f.BriefName)); //4 多field模糊匹配 组合参数时,不能用非字符类型的field去匹配字符 例如数字类型的price字段不能和字符类型的productName一起做多field匹配 Field [] fields = new Field[2]; fields[0]=Field.Create("productName", 1); fields[1] = Field.Create("briefName", 1); //Operator操作符决定了用于匹配的所有field中是否需要同时包含keywords的所有分词后的搜索词 //【keywords 理解为分词后以空格分割的词语,如:新西兰香蕉=>新西兰 香蕉】如果Operator为And 则productName和briefName 中必须包含“新西兰”和“香蕉”这两个词(可以是productName包含“新西兰”,briefName包含“香蕉”) //如果Operator为or 则productName和briefName 中任意一个field包含(新西兰或香蕉)的中任意一个词语 即可搜到 QueryContainer mmq = Query<Product>.MultiMatch(mm => mm.Query(keywords).Fields(fields).Operator(Operator.Or)); //最终组合的查询条件 query 查询ApplayRangetype不是2的 且在指定时间范围内的,搜索关键词命中的商品 QueryContainer query = Query<Product>.Bool(b => b.MustNot(q).Must(drq).Must(mmq)); #endregion #region 组合搜索参数 查询条件,排序,聚合,条数 SearchRequest<Product> request=new SearchRequest<Product> ("shuaiproduct","product"); request.Query = query; //request.Aggregations //聚合 //searchRequest.Sort //排序 request.From = 0; request.Size = 10; request.Routing = new string[] { "1" }; //指定路由值(此处为导入数据的时候的applyrange的值) #endregion //执行搜索 var client = ElasticSearchCommon.GetInstance().GetElasticClient(); var result = client.Search<Product>(request); }
连接:
public ElasticClient GetElasticClient() { //链接elasticsearch var node = new Uri("http://192.168.1.60:19200"); var settings = new ConnectionSettings(node);//使用连接池 node改为 ConnectionPool var client = new ElasticClient(settings); return client; } //es连接池 public static SniffingConnectionPool ConnectionPool { get { if (connectionPool == null) { var uris = new List<Uri>(); string[] urls = { "http://192.168.60.1:19200", "http://192.168.1.61:19200" }; foreach (var uri in urls) { uris.Add(new Uri(uri)); } connectionPool = new SniffingConnectionPool(uris); } return connectionPool; } }