全文检索-Elasticsearch (四) elasticsearch.net 客户端

本篇摘自elasticsearch.net search入门使用指南中文版(翻译)html

原文:http://edu.dmeiyang.com/book/nestusing.htmlnode

elasticsearch.net为何会有两个客户端?

  • Elasticsearch.Net是一个很是底层且灵活的客户端,它不在乎你如何的构建本身的请求和响应。它很是抽象,所以全部的Elasticsearch API被表示为方法,没有太多关于你想如何构建json/request/response对象的东东,而且它还内置了可配置、可重写的集群故障转移机制。
  • Elasticsearch.Net有很是大的弹性,若是你想更好的提高你的搜索服务,你彻底可使用它来作为你的客户端。
  • NEST是一个高层的客户端,能够映射全部请求和响应对象,拥有一个强类型查询DSL(领域特定语言),而且可使用.net的特性好比协变、Auto Mapping Of POCOs,NEST内部使用的依然是Elasticsearch.Net客户端。

NEST Client

1、如何安装NEST

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

Install-Package NEST

安装后引用了如下三个DLLapp

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

2、连接elasticsearch

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

经过单点连接:elasticsearch

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

经过链接池连接:ide

var nodes = new Uri[]
{
    new Uri("http://myserver1:9200"),
    new Uri("http://myserver2:9200"),
    new Uri("http://myserver3:9200")
};

var pool = new StaticConnectionPool(nodes);
var settings = new ConnectionSettings(pool);
var client = new ElasticClient(settings);

NEST Index

为了知道请求须要操做哪一个索引,Elasticsearch API指望收到一个或多个索引名称做为请求的一部分函数

 1、指定索引

一、能够经过ConnectionSettings使用.DefaultIndex(),来指定默认索引。当一个请求里没有指定具体索引时,NEST将请求默认索引。工具

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

二、能够经过ConnectionSettings使用.MapDefaultTypeIndices(),来指定被映射为CLR类型的索引。ui

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

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

三、另外还能够显示的为请求指定索引名称,例如:

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

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

四、一些Elasticsearch API(好比query)能够采用一个、多个索引名称或者使用_all特殊标志发送请求,请求NEST上的多个或者全部节点

//请求单一节点
var singleString = Nest.Indices.Index("db_studnet");
var singleTyped = Nest.Indices.Index<Student>();

ISearchRequest singleStringRequest = new SearchDescriptor<Student>().Index(singleString);
ISearchRequest singleTypedRequest = new SearchDescriptor<Student>().Index(singleTyped);

//请求多个节点
var manyStrings = Nest.Indices.Index("db_studnet", "db_other_student");
var manyTypes = Nest.Indices.Index<Student>().And<OtherStudent>();

ISearchRequest manyStringRequest = new SearchDescriptor<Student>().Index(manyStrings);
ISearchRequest manyTypedRequest = new SearchDescriptor<Student>().Index(manyTypes);

//请求全部节点
var indicesAll = Nest.Indices.All;
var allIndices = Nest.Indices.AllIndices;

ISearchRequest indicesAllRequest = new SearchDescriptor<Student>().Index(indicesAll);
ISearchRequest allIndicesRequest = new SearchDescriptor<Student>().Index(allIndices);

2、建立索引

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

var descriptor = new CreateIndexDescriptor("db_student")
    .Settings(s => s.NumberOfShards(5).NumberOfReplicas(1));

client.CreateIndex(descriptor);

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

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

NEST Mapping

1、简单实现

一、定义业务须要的POCO,并指定须要的Attribute

[ElasticsearchType(Name = "student")]
public class Student
{
    [Nest.String(Index = FieldIndexOption.NotAnalyzed)]
    public string Id { get; set; }

    [Nest.String(Analyzer = "standard")]
    public string Name { get; set; }

    [Nest.String(Analyzer = "standard")]
    public string Description { get; set; }

    public DateTime DateTime { get; set; }
}

二、接着咱们经过.AutoMap()来实现映射

var descriptor = new CreateIndexDescriptor("db_student")
    .Settings(s => s.NumberOfShards(5).NumberOfReplicas(1))
    .Mappings(ms => ms
        .Map<Student>(m => m.AutoMap())
    );

client.CreateIndex(descriptor);

注意:经过.Properties()能够重写经过Attribute定义的映射

2、Attribute介绍

一、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

二、NumberAttribute

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

三、BooleanAttribute

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

四、DateAttribute

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

五、ObjectAttribute

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

NEST Search

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

1、简单实现

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

var query = new Nest.SearchDescriptor<Models.ESObject>();

var result = client.Search<Student>(x => query)

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

query.Query(q =>
    q.Bool(b =>
        b.Must(m =>
            m.MultiMatch(t => t.Fields(f => f.Field(obj => obj.Title).Field(obj => obj.Content)).Query(key))
        )
        .MustNot(m =>
            m.QueryString(t => t.Fields(f => f.Field(obj => obj.Author)).Query("俏佳人"))
        )
    )
);

注意:

  • 若是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)],禁止使用分析器

三、过滤做者等于“历史小河”的文档

query.PostFilter(x => x.Term(t => t.Field(obj => obj.Author).Value("历史小河")));

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

query.PostFilter(x => x.QueryString(t => t.Fields(f => f.Field(obj => obj.Author)).Query("历史小河 友谊的小船")));

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

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

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

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

七、定义高亮样式及字段

query.Highlight(h => h
    .PreTags("<b>")
    .PostTags("</b>")
    .Fields(
        f => f.Field(obj => obj.Title),
        f => f.Field(obj => obj.Content),
        f => f.Field("_all")
    )
);

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

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

elasticsearch.net Document

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

1、添加/更新文档及批量操做

添加/更新单一文档

Client.Index(student);

批量添加/更新文档

var list = new List<Student>();

client.IndexMany<Student>(list);

2、局部更新单一文档及批量操做

局部更新单一文档

client.Update<Student, object>("002", upt => upt.Doc(new { Name = "江山美人" }));

局部更新批量文档

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 = "胡一刀" };

    bulkQuest.Operations.Add(operation);
}

var result = client.Bulk(bulkQuest);

3、删除文档及批量操做

删除单一文档

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

批量删除文档

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

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

foreach (var v in ids)
{
    bulkQuest.Operations.Add(new BulkDeleteOperation<Student>(v));
}

var result = client.Bulk(bulkQuest);
相关文章
相关标签/搜索