C#如何使用ES

Elasticsearch简介

Elasticsearch (ES)是一个基于Apache Lucene(TM)的开源搜索引擎,无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。

但是,Lucene只是一个库。想要发挥其强大的作用,你需使用C#将其集成到你的应用中。Lucene非常复杂,你需要深入的了解检索相关知识来理解它是如何工作的。 
Elasticsearch是使用Java编写并使用Lucene来建立索引并实现搜索功能,但是它的目的是通过简单连贯的RESTful API让全文搜索变得简单并隐藏Lucene的复杂性。 
不过,Elasticsearch不仅仅是Lucene和全文搜索引擎,它还提供:

  • 分布式的实时文件存储,每个字段都被索引并可被搜索
  • 实时分析的分布式搜索引擎
  • 可以扩展到上百台服务器,处理PB级结构化或非结构化数据

而且,所有的这些功能被集成到一台服务器,你的应用可以通过简单的RESTful API、各种语言的客户端甚至命令行与之交互。上手Elasticsearch非常简单,它提供了许多合理的缺省值,并对初学者隐藏了复杂的搜索引擎理论。它开箱即用(安装即可使用),只需很少的学习既可在生产环境中使用。Elasticsearch在Apache 2 license下许可使用,可以免费下载、使用和修改。 
随着知识的积累,你可以根据不同的问题领域定制Elasticsearch的高级特性,这一切都是可配置的,并且配置非常灵活。

以上内容来自 [百度百科]

关于ES详细概念见:http://88250.b3log.org/full-text-search-elasticsearch#b3_solo_h3_0

使用C#操作ES

NEST是一个高层的客户端,可以映射所有请求和响应对象,拥有一个强类型查询DSL(领域特定语言),并且可以使用.net的特性比如协变、Auto Mapping Of POCOs,NEST内部使用的依然是Elasticsearch.Net客户端。elasticsearch.net(NEST)客户端提供了强类型查询DSL,方便用户使用,源码下载

一、如何安装NEST

打开VS的工具菜单,通过NuGet包管理器控制台,输入以下命令安装NEST

Install-Package NEST

安装后引用了以下三个DLL

Elasticsearch.Net.dll(2.4.4)
Nest.dll(2.4.4)
Newtonsoft.Json.dll(9.0版本)

二、链接elasticsearch

你可以通过单个节点或者指定多个节点使用连接池链接到Elasticsearch集群,使用连接池要比单个节点链接到Elasticsearch更有优势,比如支持负载均衡、故障转移等。

通过单点链接:

1 var node = new Uri("http://myserver:9200");
2 var settings = new ConnectionSettings(node);
3 var client = new ElasticClient(settings);

通过连接池链接:

 1 var nodes = new Uri[]
2 {
3 new Uri("http://myserver1:9200"),
4 new Uri("http://myserver2:9200"),
5 new Uri("http://myserver3:9200")
6 };
7
8 var pool = new StaticConnectionPool(nodes);
9 var settings = new ConnectionSettings(pool);
10 var client = new ElasticClient(settings);

NEST Index

为了知道请求需要操作哪个索引,Elasticsearch API期望收到一个或多个索引名称作为请求的一部分。

一、指定索引

1、可以通过ConnectionSettings使用.DefaultIndex(),来指定默认索引。当一个请求里没有指定具体索引时,NEST将请求默认索引。

1 var settings = new ConnectionSettings()
2 .DefaultIndex("defaultindex");

2、可以通过ConnectionSettings使用.MapDefaultTypeIndices(),来指定被映射为CLR类型的索引。

1 var settings = new ConnectionSettings()
2 .MapDefaultTypeIndices(m => m
3 .Add(typeof(Project), "projects")
4 );

注意:通过.MapDefaultTypeIndices()指定索引的优先级要高于通过.DefaultIndex()指定索引,并且更适合简单对象(POCO)

3、另外还可以显示的为请求指定索引名称,例如:

1 var response = client.Index(student, s=>s.Index("db_test"));
2 var result = client.Search<Student>(s => s.Index("db_test"));
3 var result = client.Delete<Student>(null, s => s.Index("db_test"));
4 ……

注意:当现实的为请求指定索引名称时,这个优先级是最高的,高于以上两种方式指定的索引。

4、一些Elasticsearch API(比如query)可以采用一个、多个索引名称或者使用_all特殊标志发送请求,请求NEST上的多个或者所有节点

 1 //请求单一节点
2 var singleString = Nest.Indices.Index("db_studnet");
3 var singleTyped = Nest.Indices.Index<Student>();
4
5 ISearchRequest singleStringRequest = new SearchDescriptor<Student>().Index(singleString);
6 ISearchRequest singleTypedRequest = new SearchDescriptor<Student>().Index(singleTyped);
7
8 //请求多个节点
9 var manyStrings = Nest.Indices.Index("db_studnet", "db_other_student");
10 var manyTypes = Nest.Indices.Index<Student>().And<OtherStudent>();
11
12 ISearchRequest manyStringRequest = new SearchDescriptor<Student>().Index(manyStrings);
13 ISearchRequest manyTypedRequest = new SearchDescriptor<Student>().Index(manyTypes);
14
15 //请求所有节点
16 var indicesAll = Nest.Indices.All;
17 var allIndices = Nest.Indices.AllIndices;
18
19 ISearchRequest indicesAllRequest = new SearchDescriptor<Student>().Index(indicesAll);
20 ISearchRequest allIndicesRequest = new SearchDescriptor<Student>().Index(allIndices);

二、创建索引

Elasticsearch API允许你创建索引的同时对索引进行配置,例如:

1 var descriptor = new CreateIndexDescriptor("db_student")
2 .Settings(s => s.NumberOfShards(5).NumberOfReplicas(1));
3
4 client.CreateIndex(descriptor);

这里指定了该索引的分片数为5、副本数为1。

三、删除索引

Elasticsearch API允许你删除索引,例如:

1 var descriptor = new DeleteIndexDescriptor("db_student").Index("db_student");
2
3 client.DeleteIndex(descriptor)

这里制定了要删除的索引名称“db_student”,以下为更多删除用例:

1 //删除指定索引所在节点下的所有索引
2 var descriptor = new DeleteIndexDescriptor("db_student").AllIndices();

NEST Mapping

NEST提供了多种映射方法,这里介绍下通过Attribute自定义映射。

一、简单实现

1、定义业务需要的POCO,并指定需要的Attribute

 1 [ElasticsearchType(Name = "student")]
2 public class Student
3 {
4 [Nest.String(Index = FieldIndexOption.NotAnalyzed)]
5 public string Id { get; set; }
6
7 [Nest.String(Analyzer = "standard")]
8 public string Name { get; set; }
9
10 [Nest.String(Analyzer = "standard")]
11 public string Description { get; set; }
12
13 public DateTime DateTime { get; set; }
14 }

2、接着我们通过.AutoMap()来实现映射

1 var descriptor = new CreateIndexDescriptor("db_student")
2 .Settings(s => s.NumberOfShards(5).NumberOfReplicas(1))
3 .Mappings(ms => ms
4 .Map<Student>(m => m.AutoMap())
5 );
6
7 client.CreateIndex(descriptor);

注意:通过.Properties()可以重写通过Attribute定义的映射

二、Attribute介绍

1、StringAttribute

属性名 值类型 描述
Analyzer string 分析器名称,值包含standard、simple、whitespace、stop、keyward、pattern、language、snowball、custom等,查看分析器更多信息请点击Elasticsearch Analyzers
Boost double 加权值,值越大得分越高
NullValue string 插入文档时,如果数据为NULL时的默认值
Index FieldIndexOption 是否使用分析器,默认使用FieldIndexOption.Analyzed,禁止使用分析器FieldIndexOption.NotAnalyzed

2、NumberAttribute

属性名 值类型 描述
type NumberType 构造函数参数,指定当前属性的类型,NumberType.Default、Float、Double、Integer、Long、Short、Byte
Boost double 加权值,值越大得分越高
NullValue double 插入文档时,如果数据为NULL时的默认值

3、BooleanAttribute

属性名 值类型 描述
Boost double 加权值,值越大得分越高
NullValue double 插入文档时,如果数据为NULL时的默认值

4、DateAttribute

属性名 值类型 描述
Boost double 加权值,值越大得分越高
NullValue string 插入文档时,如果数据为NULL时的默认值
Format string  

5、ObjectAttribute

属性名 值类型 描述
type string/Type 构造函数参数,指定当前属性的类型T
Dynamic DynamicMapping  

NEST Search

NEST提供了支持Lambda链式query DLS(领域特定语言)方式,以下是简单实现及各个query的简述。

一、简单实现

1、定义SearchDescriptor,方便项目中复杂业务的实现

1 var query = new Nest.SearchDescriptor<Models.ESObject>();
2
3 var result = client.Search<Student>(x => query)

2、检索title和content中包含key,并且作者不等于“俏佳人”的文档

 1 query.Query(q =>
2 q.Bool(b =>
3 b.Must(m =>
4 m.MultiMatch(t => t.Fields(f => f.Field(obj => obj.Title).Field(obj => obj.Content)).Query(key))
5 )
6 .MustNot(m =>
7 m.QueryString(t => t.Fields(f => f.Field(obj => obj.Author)).Query("wenli"))
8 )
9 )
10 );
 

注意:

如果Elasticsearch使用默认分词,Title和Content的attribute为[Nest.String(Analyzer = "standard")]

如果Elasticsearch使用的是IK分词,Title和Content的attribute为[Nest.String(Analyzer = "ikmaxword")]或者[Nest.String(Analyzer = "ik_smart")]

Author的attribute为[Nest.String(Index = FieldIndexOption.NotAnalyzed)],禁止使用分析器

3、过滤作者等于“历史小河”的文档

query.PostFilter(x => x.Term(t => t.Field(obj => obj.Author).Value("wenli")));

4、过滤作者等于“历史小河”或者等于“友谊的小船”的文档,匹配多个作者中间用空格隔开

1 query.PostFilter(x => x.QueryString(t => t.Fields(f => f.Field(obj => obj.Author)).Query("wenli yswenli")));

5、过滤数量在1~100之间的文档

1 query.PostFilter(x => x.Range(t => t.Field(obj => obj.Number).GreaterThanOrEquals(1).LessThanOrEquals(100)));

6、排序,按照得分倒叙排列

1 query.Sort(x => x.Field("_score", Nest.SortOrder.Descending));

7、定义高亮样式及字段

1 query.Highlight(h => h
2 .PreTags("<b>")
3 .PostTags("</b>")
4 .Fields(
5 f => f.Field(obj => obj.Title),
6 f => f.Field(obj => obj.Content),
7 f => f.Field("_all")
8 )
9 );

8、拼装查询内容,整理数据,方便前段调用

 1 var list = result.Hits.Select(c => new Models.ESObject()
2 {
3 Id = c.Source.Id,
4 Title = c.Highlights == null ? c.Source.Title : c.Highlights.Keys.Contains("title") ? string.Join("", c.Highlights["title"].Highlights) : c.Source.Title, //高亮显示的内容,一条记录中出现了几次
5 Content = c.Highlights == null ? c.Source.Content : c.Highlights.Keys.Contains("content") ? string.Join("", c.Highlights["content"].Highlights) : c.Source.Content, //高亮显示的内容,一条记录中出现了几次
6 Author = c.Source.Author,
7 Number = c.Source.Number,
8 IsDisplay = c.Source.IsDisplay,
9 Tags = c.Source.Tags,
10 Comments = c.Source.Comments,
11 DateTime = c.Source.DateTime,
12 })

二、query DSL介绍

待整理……

elasticsearch.net Document

文档操作包含添加/更新文档、局部更新文档、删除文档及对应的批量操作文档方法。

一、添加/更新文档及批量操作

添加/更新单一文档

1 Client.Index(student);

批量添加/更新文档

1 var list = new List<Student>();
2
3 client.IndexMany<Student>(list);

二、局部更新单一文档及批量操作

局部更新单一文档

1 client.Update<Student, object>("002", upt => upt.Doc(new { Name = "wenli" }));

局部更新批量文档

var ids = new List<string>() { "002" };

var bulkQuest = new BulkRequest() { Operations = new List<IBulkOperation>() };

foreach (var v in ids)
{
var operation = new BulkUpdateOperation<Student, object>(v); operation.Doc = new { Name = "wenli" }; bulkQuest.Operations.Add(operation);
} var result = client.Bulk(bulkQuest);

三、删除文档及批量操作

删除单一文档

1 client.Delete<Student>("001");

批量删除文档

 1 var ids = new List<string>() { "001", "002" };
2
3 var bulkQuest = new BulkRequest() { Operations = new List<IBulkOperation>() };
4
5 foreach (var v in ids)
6 {
7 bulkQuest.Operations.Add(new BulkDeleteOperation<Student>(v));
8 }
9
10 var result = client.Bulk(bulkQuest);

转载请标明本文来源:http://www.cnblogs.com/yswenli/
更多内容欢迎我的的github:https://github.com/yswenli
如果发现本文有什么问题和任何建议,也随时欢迎交流~

C#使用ES的更多相关文章

  1. 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)

    0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...

  2. OpenGL ES 3.0: 图元重启(Primitive restart)

    [TOC] 背景概述 在OpenGL绘制图形时,可能需要绘制多个并不相连的图形.这样的情况下这几个图形没法被当做一个图形来处理.也就需要多次调用 DrawArrays 或 DrawElements. ...

  3. 分享一个CQRS/ES架构中基于写文件的EventStore的设计思路

    最近打算用C#实现一个基于文件的EventStore. 什么是EventStore 关于什么是EventStore,如果还不清楚的朋友可以去了解下CQRS/Event Sourcing这种架构,我博客 ...

  4. ES 学习总结

    ES 总结: es 是基于lucene的, 是java 实现的, 很多概念和lucene是相同的 索引-- 对应数据库的表,mongoDB中的集合 文档,由字段组成, 一个字段可以出现多次. 字段,其 ...

  5. ES性能测试

    测试背景   因为ES(ElasticSearch)前段时间查询效率有点慢,技术小组对索引做了一些改动,因此需要测试一下修改后的查询效率,跟之前的结果做一下对比,所以有了这次测试.   需求简述   ...

  6. [翻译]ES 提案: global

    Jordan Harband 的 ECMAScript 提案“global”现在处于第三阶段.该提案提供了一种新的用于访问全局对象的标准方式. 全局对象的引用 下面是常用的几种引用全局对象的方式: 全 ...

  7. ElasticSearch+ElasticGeo+Geoserver发布ES地理数据

    依赖GeoserverElasticSearchElasticGeo部署部署ElasticGeo使用创建ES数据源并发布发布 依赖 Geoserver 环境搭建参考: ElasticSearch 环境 ...

  8. opengl es中不同的绘制方式

    opengl es中不同的绘制方式 转载请保留出处:http://xiaxveliang.blog.163.com/blog/static/297080342013467344263/ 1. GL_P ...

  9. es查询命令备份(只需要网页9200/_plugin/head/就可以访问)

    本文只是写一些常用es命令,这里不用任何客户端,只用 9200/_plugin/head/ 那个端口网页就可以,然后是复合查询. 注意es其实一个idnex只能有一个type,如果一个index做了多 ...

  10. lucene和es总结

    一.首先介绍lucene涉及到的排序过程 1.1.如何自定义排序对象 你可以自定义collector对象: 亦可以自定义comparator对象: 可以自定义scoredoc对象,决定如何处理结果集合 ...

随机推荐

  1. JAVA API的下载和中文查看API

    一.JAVA API的下载 1.1 JAVA由SUN公司开发,2006年SUN公司宣布将Java技术作为免费软件对外发布,标志着JAVA的公开免费.2009年,SUN公司被甲骨文公司收购,因此我们现在 ...

  2. 《Java大学教程》—第13章 程序包

    接下来,是第二学期的内容,也是相对深入的Java学习. 自测题:1.    在类的开发过程中,程序包的作用是什么?P321程序包是为了方便定位和部署类,还可以避免将来类之间出现名称冲突. 2.    ...

  3. ORC Creation Best Practices

    Short Description: ORC Creation Best Practices with examples and references. Article Synopsis. ORC i ...

  4. 为什么react的组件要super(props)

    https://segmentfault.com/q/1010000008340434

  5. (转)Spring Boot (十五): Spring Boot + Jpa + Thymeleaf 增删改查示例

    http://www.ityouknow.com/springboot/2017/09/23/spring-boot-jpa-thymeleaf-curd.html 这篇文章介绍如何使用 Jpa 和 ...

  6. php面试题整理(五)

    表单也得改

  7. python六十四课——高阶函数练习题(一)

    1.lt = ['sdfasdfa', 'ewqrewrewqr', 'dsafa12312fdsafd', 'safsadf'] --> 得到长度列表2.tp = ('TOM', 'Lilei ...

  8. [CQOI2016]手机号码

    嘟嘟嘟 这题一看就是数位dp. 我写数位dp,一般是按数位dp的格式写一个爆搜,然后加一点记忆化. 不过其实我一直不是很清楚记忆化是怎么加,感觉就是把dfs里的参数都扔到dp数组里,好像很暴力啊. 这 ...

  9. 转://如何增加linux根目录的磁盘空间(基于LVM)?

    问题引出: 在测试过程中替换so文件,报磁盘空间不足的错误. ▲问题分析: 由于当时系统部署架构的考虑,把软件和数据库部署在了同一台机器上,并且给了30G的磁盘空间.系统上占用磁盘空间的有2部分,一是 ...

  10. sql 查询所有子节点示例

    每天学习一点点 编程PDF电子书.视频教程免费下载:http://www.shitanlife.com/code <!-- 查询机构的所有子机构 --> <select id=&qu ...