创建索引模型:
#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;
}
}