全文檢索-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);
相關文章
相關標籤/搜索