Elasticsearch NEST – Examples for mapping between Query and C#

Elasticsearch NEST – Examples for mapping between Query and C#

During my training with Elasticsearch I would like to map a query with GET/POST method to C# syntax of NEST. It’s very helpful for me to see how NEST composes its internal queries and sends to Elasticsearch server. I just post my sample project here, maybe it’ll help you too.

1. Indexing Employee Documents

PUT /megacorp/employee/1

{

  "about": "I love to go rock climbing",

  "age": 25,

  "firstName": "John",

  "id": 1,

  "interests": [

    "sports",

    "music"

  ],

  "lastName": "Smith"

}

Employee employee = new Employee()

{

    Id = 1,

    FirstName = "John",

    LastName = "Smith",

    Age = 25,

    About = "I love to go rock climbing",

    Interests = new List<string>() { "sports", "music" }

};

await client.IndexAsync(employee);

2. Retrieving a Document

GET /megacorp/employee/1

{

  "_index" : "megacorp",

  "_type" : "employee",

  "_id" : "1",

  "_version" : 9,

  "found" : true,

  "_source" : {

    "about" : "I love to go rock climbing",

    "age" : 25,

    "firstName" : "John",

    "id" : 1,

    "interests" : [ "sports", "music" ],

    "lastName" : "Smith"

  }

}

public async Task<T> GetById(int id)

{

    var response = await client.GetAsync<T>(new DocumentPath<T>(id), g => g.Index(defaultIndex).Type(defaultType));

    return response.Source;

}

3. Search Lite

We will search for all employees, with this request

POST http://localhost:9200/megacorp/employee/_search?pretty=true

{}

public async Task<IEnumerable<T>> SearchAsync()

{

    var response = await client.SearchAsync<T>(s => s.Type(defaultType));

    return response.Documents;

}

4. Search with Query DSL

We can represent the search for all Smiths like so

POST http://localhost:9200/megacorp/employee/_search?pretty=true

{

    "query": {

    "match": {

        "lastName": {

            "query": "Smith"

        }

    }

    }

}

public async Task ExecuteAsync()

{

    var result = await client.SearchAsync<Employee>(

        s =>

            s.Type(typeEmployee)

                .Query(q => q.Match(m => m.Field(f => f.LastName).Query("Smith"))));

    Result = result.Documents;

}

5. Search with Query String

POST http://localhost:9200/megacorp/employee/_search?pretty=true

{

  "query": {

    "query_string": {

      "query": "Smith",

      "fields": [

        "lastName"

      ]

    }

  }

}

public async Task ExecuteAsync()

{

    var result = await client.SearchAsync<Employee>(

        s =>

            s.Type(typeEmployee)

                .Query(q => q.QueryString(qs =>

                    qs.Fields(f => f.Field(fi => fi.LastName))

                        .Query("Smith"))));

    Result = result.Documents;

}

6. More-Complicated Searches

POST http://localhost:9200/megacorp/employee/_search?pretty=true

{

  "query": {

    "bool": {

      "must": [

        {

          "match": {

            "lastName": {

              "query": "smith"

            }

          }

        }

      ],

      "filter": [

        {

          "range": {

            "age": {

              "gt": 30.0

            }

          }

        }

      ]

    }

  }

}

public async Task ExecuteAsync()

{

    var result = await client.SearchAsync<Employee>(

        s =>

            s.Type(typeEmployee)

                .Query(q => q.Bool(b =>

                    b.Filter(f =>

                        f.Range(r =>

                            r.Field(fi => fi.Age).GreaterThan(30)))

                   .Must(m =>

                        m.Match(ma =>

                            ma.Field(fie => fie.LastName).Query("smith")))

                    )));

    Result = result.Documents;

}

7. Full-Text Search

We are going to search for all employees who enjoy “rock climbing”, “rock” or “climbing”.

POST http://localhost:9200/megacorp/employee/_search?pretty=true

{

  "query": {

    "match": {

      "about": {

        "query": "rock climbing"

      }

    }

  }

}

public async Task ExecuteAsync()

{

    var result = await client.SearchAsync<Employee>(

        s =>

            s.Type(typeEmployee)

                .Query(q =>

                    q.Match(m =>

                        m.Field(f => f.About).Query("rock climbing"))

                   ));

    Result = result.Documents;

}

8. Phrase Search

Finding individual words in a field is all well and good, but sometimes you want to
match exact sequences of words or phrases. For instance, we could perform a query
that will match only employee records that contain both “rock” and “climbing” and
that display the words are next to each other in the phrase “rock climbing.”

POST http://localhost:9200/megacorp/employee/_search?pretty=true

{

  "query": {

    "match": {

      "about": {

        "type": "phrase",

        "query": "rock climbing"

      }

    }

  }

}

public async Task ExecuteAsync()

{

    var result = await client.SearchAsync<Employee>(

        s =>

            s.Type(typeEmployee)

                .Query(q =>

                    q.MatchPhrase(m =>

                        m.Field(f => f.About).Query("rock climbing"))

                   ));

    Result = result.Documents;

}

9. Highlighting Our Searches

Many applications like to highlight snippets of text from each search result so the user
can see why the document matched the query

POST http://localhost:9200/megacorp/employee/_search?pretty=true

{

  "highlight": {

    "fields": {

      "about": {}

    }

  },

  "query": {

    "match": {

      "about": {

        "type": "phrase",

        "query": "rock climbing"

      }

    }

  }

}

public async Task ExecuteAsync()

{

    var result = await client.SearchAsync<Employee>(

        s =>

            s.Type(typeEmployee)

                .Query(q =>

                    q.MatchPhrase(m =>

                        m.Field(f => f.About).Query("rock climbing")))

                .Highlight(h => h.Fields(fi => fi.Field(fie => fie.About)))

        );

    Result = result.Hits;

}

10. Analytics

Let’s find the most popular interests enjoyed by our employees

POST http://localhost:9200/megacorp/employee/_search?pretty=true

{

  "aggs": {

    "all_interests": {

      "terms": {

        "field": "interests"

      }

    }

  }

}

public async Task ExecuteAsync()

{

    var result = await client.SearchAsync<Employee>(

        s =>

            s.Type(typeEmployee)

                .Aggregations(a =>

                    a.Terms("all_interests", t =>

                        t.Field(f => f.Interests)))

        );

    Result = result.Aggregations;

}

11. Analytics limit

If we want to know the popular interests of people called Smith, we can just add the appropriate query into the mix:

POST http://localhost:9200/megacorp/employee/_search?pretty=true

{

  "aggs": {

    "all_interests": {

      "terms": {

        "field": "interests"

      }

    }

  },

  "query": {

    "match": {

      "lastName": {

        "query": "smith"

      }

    }

  }

}

public async Task ExecuteAsync()

{

    var result = await client.SearchAsync<Employee>(

        s =>

            s.Type(typeEmployee)

                .Query(q =>

                    q.Match(m =>

                        m.Field(fi =>

                            fi.LastName).Query("smith")))

                .Aggregations(a =>

                    a.Terms("all_interests", t =>

                        t.Field(f => f.Interests)))

        );

    Result = result.Aggregations;

}

12. Analytics with Average

POST http://localhost:9200/megacorp/employee/_search?pretty=true

{

  "aggs": {

    "all_interests": {

      "terms": {

        "field": "interests"

      },

      "aggs": {

        "avg_age": {

          "avg": {

            "field": "age"

          }

        }

      }

    }

  }

}

public async Task ExecuteAsync()

{

    var result = await client.SearchAsync<Employee>(

        s =>

            s.Type(typeEmployee)

                .Aggregations(a =>

                    a.Terms("all_interests", t =>

                        t.Field(f =>

                            f.Interests)

                        .Aggregations(ag =>

                            ag.Average("avg_age", av =>

                                av.Field(fi => fi.Age)))

                    )

                )

        );

    Result = result.Aggregations;

}

13. Retrieving Part of a Document

GET http://localhost:9200/website/blog/123?pretty=true&fields=title%2Ctext

public async Task ExecuteAsync()

{

    var response =

        await client.GetAsync(new DocumentPath<Blog>(123), g =>

                    g.Fields(f => f.Title, f => f.Text));

    Result = response.Fields;

}

14. Updating a Whole Document

PUT http://localhost:9200/website/blog/123?pretty=true

{

  "date": "2014-01-01T00:00:00",

  "id": 123,

  "text": "I am staring to get the hang of this...",

  "title": "My first blog entry"

}

public async Task ExecuteAsync()

{

    var blog = new Blog()

    {

        Id = 123,

        Title = "My first blog entry",

        Text = "I am staring to get the hang of this...",

        Date = new DateTime(2014, 1, 1)

    };

    Result = await client.UpdateAsync(new DocumentPath<Blog>(123), u => u.Doc(blog));

}

15. Partial Updates to Documents

POST http://localhost:9200/website/blog/1/_update?pretty=true

{

  "doc": {

    "tags": [

      "testing"

    ],

    "views": 0

  }

}

public async Task ExecuteAsync()

{

    var blog = new Blog()

    {

        Id = 1,

        Title = "My first blog entry",

        Text = "Just trying this out..."

    };

    await client.IndexAsync(blog);

    dynamic dyn = new ExpandoObject();

    dyn.Tags = new List<string>() { "testing" };

    dyn.Views = 0;

    Result = await client.UpdateAsync<Blog, dynamic>(new DocumentPath<Blog>(1), u =>

         u.Doc(dyn));

}

16. Deleting a Document

DELETE http://localhost:9200/website/blog/123?pretty=true

public async Task ExecuteAsync()

{

    Result = await client.DeleteAsync(new DocumentPath<Blog>(123));

}

17. Cluster Health

GET http://localhost:9200/_cluster/health?pretty=true

public async Task ExecuteAsync()

{

    Result = await client.ClusterHealthAsync();

}

18. Add an Index

PUT http://localhost:9200/blogs?pretty=true

{

  "settings": {

    "index.number_of_replicas": 1,

    "index.number_of_shards": 3

  }

}

public async Task ExecuteAsync()

{

    Result = await client.CreateIndexAsync("blogs", c =>

                 c.Settings(s =>

                     s.NumberOfShards(3)

                     .NumberOfReplicas(1)));

}

19. Retrieving Part of a Document

GET http://localhost:9200/website/blog/123?pretty=true&_source_include=title%2Ctext

public async Task ExecuteAsync()

{

    Result =

        await client.GetAsync<Blog>(new DocumentPath<Blog>(123), g =>

             g.SourceInclude("title", "text"));

}

20. Using Versions from an External System

PUT http://localhost:9200/website/blog/2?pretty=true&version=25&version_type=external

{

  "date": "0001-01-01T00:00:00",

  "id": 0,

  "text": "Starting to get the hang of this...",

  "title": "My first external blog entry",

  "views": 0

}

public async Task ExecuteAsync()

{

    var getResponse = (await client.GetAsync<Blog>(new DocumentPath<Blog>(2)));

    var blog = getResponse.Source;

    long version;

    if (blog == null)

    {

        blog = new Blog()

        {

            Title = "My first external blog entry",

            Text = "Starting to get the hang of this..."

        };

        var result = await client.IndexAsync(blog, i => i.Id(2));

        version = result.Version;

    }

    else

        version = getResponse.Version;

    Result = await client.IndexAsync(blog, i => i.Id(2).Version(version + 5).VersionType(VersionType.External));

}

21. Using Scripts to Make Partial Updates

POST http://localhost:9200/website/blog/1/_update?pretty=true

{

  "script": "ctx._source.views += 1"

}

public async Task ExecuteAsync()

{

    Result = await client.UpdateAsync(new DocumentPath<Blog>(1), u =>

        u.Script("ctx._source.views += 1"));

}

POST http://localhost:9200/website/blog/1/_update?pretty=true

{

  "script": "ctx._source.tags+=new_tag",

  "params": {

    "new_tag": "search"

  }

}

public async Task ExecuteAsync()

{

    Result = await client.UpdateAsync(new DocumentPath<Blog>(1), u =>

        u.Script("ctx._source.tags+=new_tag")

        .Params(p => p.Add("new_tag", "search")));

}

POST http://localhost:9200/website/blog/1/_update?pretty=true

{

  "script": "ctx.op = ctx._source.views == count ? ‘delete‘ : ‘none‘",

  "params": {

    "count": "1"

  }

}

Result = await client.UpdateAsync(new DocumentPath<Blog>(1), u =>

                u.Script("ctx.op = ctx._source.views == count ? ‘delete‘ : ‘none‘")

                .Params(p => p.Add("count", "1")));

22. Updating a Document That May Not Yet Exist

Imagine that we need to store a page view counter in Elasticsearch. Every time that a user views a page, we increment the counter for that page. But if it is a new page, we can’t be sure that the counter already exists. If we try to update a nonexistent document, the update will fail.
In cases like these, we can use the upsert parameter to specify the document that should be created if it doesn’t already exist

POST http://localhost:9200/website/pageviews/1/_update?pretty=true

{

  "script": "ctx._source.views+=1",

  "upsert": {

    "id": 0,

    "views": 1

  }

}

public async Task ExecuteAsync()

{

    Result = await client.UpdateAsync(new DocumentPath<PageViews>(1), u =>

        u.Script("ctx._source.views+=1")

        .Upsert(new PageViews() { Views = 1 }));

}

23. Updates and Conflicts

POST http://localhost:9200/website/pageviews/1/_update?pretty=true&retry_on_conflict=5

{

  "script": "ctx._source.views+=1",

  "upsert": {

    "id": 1,

    "views": 0

  }

}

Result = await client.UpdateAsync(new DocumentPath<PageViews>(1), u =>

                u.Script("ctx._source.views+=1")

                    .Upsert(new PageViews { Id = 1, Views = 0 })

                    .RetryOnConflict(5));

24. Retrieving Multiple Documents

POST http://localhost:9200/_mget?pretty=true

{

  "docs": [

    {

      "_index": "website",

      "_type": "blog",

      "_id": 2

    },

    {

      "_index": "website",

      "_type": "pageviews",

      "_id": 1

    }

  ]

}

public async Task ExecuteAsync()

{

    Result = await client.MultiGetAsync(m =>

        m.Get<Blog>(g =>

            g.Id(2))

        .Get<PageViews>(ge =>

            ge.Id(1))

        );

}

POST http://localhost:9200/website/blog/_mget?pretty=true

{

  "ids": [

    2,

    1

  ]

}

Result = await client.MultiGetAsync(m =>

    m.Index(indexWebsite)

    .Type(typeBlog)

    .GetMany<Blog>(new long[] { 2, 1 }));

100. Source code

Source code: https://bitbucket.org/hintdesk/dotnet-elasticsearch-nest-examples-for-mapping-between-query

My strongly recommended books to read. Choose one and enjoy yourself.

时间: 2024-12-08 13:12:32

Elasticsearch NEST – Examples for mapping between Query and C#的相关文章

Elasticsearch(八)【NEST高级客户端--Mapping映射】

要使用NEST与Elasticsearch进行交互,我们需要能够将我们的解决方案中的POCO类型映射到存储在Elasticsearch中的反向索引中的JSON文档和字段.本节介绍NEST中可用的所有不同功能,使POCO和Elasticsearch变得轻而易举. 在Elasticsearch中显式映射文档对于为给定的问题域提供定制搜索解决方案至关重要.虽然Elasticsearch能够基于遇到的该类型的第一个文档来推断索引中给定类型的映射,但推测的映射有时不足以构建一个非常优秀的搜索体验. 要显式

ElasticSearch NEST笔记

1. 什么是ElasticSearch? ElasticSearch is a powerful open source search and analytics engine that makes data easy to explore. 可以简单理解成索引加检索的工具,当然它功能多于此.ElasticSearch分为服务端与客户端,服务端提供REST API,客户端使用REST API. 2.怎么安装Elastic? 安装JDK(下载地址) 安装ElasticSearch(下载地址) 解压

elasticsearch index 之 put mapping

mapping机制使得elasticsearch索引数据变的更加灵活,近乎于no schema.mapping可以在建立索引时设置,也可以在后期设置.后期设置可以是修改mapping(无法对已有的field属性进行修改,一般来说只是增加新的field)或者对没有mapping的索引设置mapping.put mapping操作必须是master节点来完成,因为它涉及到集群matedata的修改,同时它跟index和type密切相关.修改只是针对特定index的特定type. 在Action su

elasticsearch在已有mapping添加字段

最近在接手elasticsearch 方面的工作,其中向已有的mapping添加新的字段的时候,一开始在网上找 资料,发现 网上 的资料都是关于更新mapping中已有字段类型的,所以写 一篇关于向 已有mapping添加新 字段的文章,仅供elasticsearch的新手学习. curl -XPUT http://localhost:9200/test/regist/_mapping -d '{ "properties": { "user_id": { "

ElasticSearch search api的基础语法+Query DSL搜索+filter与query对比+组合查询+定位不合法的搜索

一. search api的基础语法 1.search语法 GET /search{} GET /index1,index2/type1,type2/search{} GET /_search{ "from": 0, "size": 10} 2.http协议中get是否可以带上request body HTTP协议,一般不允许get请求带上request body,但是因为get更加适合描述查询数据的操作,因此还是这么用了 GET /_search?from=0&a

elasticsearch的rest搜索---mapping

目录: 一.针对这次装B 的解释 二.下载,安装插件elasticsearch-1.7.0   三.索引的mapping 四. 查询 五.对于相关度的大牛的文档 三.mapping 1. 索引的mapping记录了对字段的描述,是否分词,是否存储等----没有细细的研究,只是简单的区分了field的不同产生的不同的mapping 2. 创建mapping,直接指定mapping,url中声明创建的索引的 { "person":{ "_all":{"enab

Elasticsearch之Nested Object Mapping

Setting up a nested field is simple-where you would normally specify type object, make it type nested instead: 创建一个nested 字段很简单--只要在你通常指定object类型的地方,改成nested类型就行: curl -XPUT 'localhost:9200/my_index' -d ' { "mappings":{ "blogpost":{ &q

ElasticSearch Index API &amp;&amp; Mapping

ElasticSearch  NEST Client 操作Index var indexName="twitter"; var deleteIndexResponse = client.DeleteIndex(indexName);                var createIndexResponse = client.CreateIndex(indexName);                var getIndexResponse = client.GetIndex(in

Query DSL for elasticsearch Query

Query DSL Query DSL (资料来自: http://www.elasticsearch.cn/guide/reference/query-dsl/) http://elasticsearch.qiniudn.com/ --简介-- elasticsearch 提供基于JSON的完整的Query DSL查询表达式(DSL即领域专用语言). 一般来说, 普通的查询如 term 或者 prefix. 另外还有混合查询如 bool 等. 另外查询表达式(Queries)还能够关联特定的过