zoukankan      html  css  js  c++  java
  • ElasticSearch7.x系列二:Kibana的使用和C#的Nest客户端

    前言

    ElasticSearch,Kibana,Logstash等安装上一章讲完了,这一章讲讲ELasticSearch怎么使用

    两种方式,一种是直接写ElasticSearch查询语句,当然是在Kibana里面

    还有一种是用代码写,可以用Java,C#,PHP,Python等,我这里使用C#

    Kibana查询ElasticSearch

    #创建
    PUT /test/user/1
    {
    	"name":"许嵩",
    	"age":34,
    	"tags":["a","b","c"]
    }
    
    #查询index里面的数量
    GET test/_count
    
    
    #查询id为1的
    GET test/user/1 
    
    
    #查询name包含许嵩的
    GET article/_search?q=title:许嵩
    
    
    # 也可以使用这种
    GET article/_search
    {
      "query": {
        "match": {
          "title": "许嵩"
        }
      }
    }
    
    # 高亮查询,讲一下,所谓的高亮就是给关键字加上自己定义的一个标签,一般都是em,然后你在css里面定义em为高亮黄色或者红色即可
    
    GET article/_search
    {
      "query": {
        "match": {
          "title": "许嵩"
        }
      },
      "highlight": {
        "pre_tags": [
          "<em>"
        ],
        "post_tags": [
          "</em>"
        ],
        "encoder": "html",
        "fields": {
          "title": {
            "force_source": true,
            "fragment_size": 150,
            "fragmenter": "span",
            "number_of_fragments": 3,
            "no_match_size": 150
          }
        }
      }
    }
    
    # 更新
    POST /test/user/1/_update
    {
    	"doc":{
    		"name":"vae"
    	}
    }
    

    使用C#的Nest查询ElasticSearch

    在NuGet里面下Nest

    连接

    var settings = new ConnectionSettings(new Uri("http://192.168.3.8:9200/")).DefaultIndex("article");
    var client = new ElasticClient(settings);
    

    使用连接池

    可以多搞几个ElasticSearch服务器

    var uris = new[]
    {
        new Uri("http://localhost:9200"),
        new Uri("http://localhost:9201"),
        new Uri("http://localhost:9202"),
    };
    
    var connectionPool = new SniffingConnectionPool(uris);
    var settings = new ConnectionSettings(connectionPool)
        .DefaultIndex("people");
    
    var client = new ElasticClient(settings);
    

    增加文档

    var person = new Person
    {
        Id = 1,
        FirstName = "Martijn",
        LastName = "Laarman"
    };
    
    //同步
    var indexResponse = client.IndexDocument(person); 
    
    //异步
    var asyncIndexResponse = await client.IndexDocumentAsync(person); 
    

    批量增加文档

    var bulkAllObservable = client.BulkAll(list, b => b
        .Index("article")
        .BackOffTime("30s")
        .BackOffRetries(2)
        .RefreshOnCompleted()
        .MaxDegreeOfParallelism(Environment.ProcessorCount)
        .Size(1000)
    )
    .Wait(TimeSpan.FromMinutes(15), next =>
    {
        // do something e.g. write number of pages to console
    });
    

    搜索文档

    1. From(0) 从0开始
    2. Size(10) 每次找10个
    3. Query 查询
    4. Match 模糊匹配
    5. Field 字段

    查询指定字段

    比如我只查标题

    var search = client.Search<AllInformationViewModel>(s => s
         .Index(indexName)
         .From(page)
         .Size(10)
         .Query(q => q
            .Match(m => m
                .Field(f => f.Title)
                .Query(keyword))
    

    全文检索

    全文检索的意思就是全部字段我都查找,标题啊,描述啊,摘要啊

    var searchAll = client.Search<AllInformationViewModel>(s => s
        .Index(indexName)
        .From(page)
        .Size(10)
        .Query(q => q
            .QueryString(qs => qs
                .Query(keyword).DefaultOperator(Operator.And))
    

    全文检索高亮

    我全文检索查的标题,描述都得给我高亮

    #方法1
    .Highlight(h => h
        .PreTags("<em>")
        .PostTags("</em>")
        .Encoder(HighlighterEncoder.Html)
        .Fields(
            fs => fs
                .Field(p => p.Title),
                
            fs => fs
                    .Field(p => p.Content)
        )
    )
        
    #方法2    
    .Highlight(h => h 
        .Fields(
            fs => fs
                .Field(p => p.Title)
                    .PreTags("<em>")
                    .PostTags("</em>"),
                
    
            fs => fs
                    .Field(p => p.Content)
                    .PreTags("<em>")
                    .PostTags("</em>")
        )
    )
    
    

    高亮查询

    public ActionResult Index(string keywords="")
    {
        var settings = new ConnectionSettings(new Uri("http://192.168.3.8:9200/")).DefaultIndex("article");
        var client = new ElasticClient(settings);
    
        var search = client.Search<Article>(s => s
            .From(0)
            .Size(10)
            .Query(q => q
                .Match(m => m
                    .Field(f => f.Title)
                    .Query(keywords))
                )
            .Highlight(h => h.Fields(e => e.Field("title")
                            .PreTags("<b style='color:red'>")
                            .PostTags("</b>")))
            //.Sort(r => r.Descending(q => q.CreateDate))
            
            //在工作中把<b style='color:red'>这个换成em标签就可以了,然后在css里面给em加上高亮即可
        );
    
        foreach (var hit in search.Hits)
        {
            foreach (var highlightField in hit.Highlight)
            {
                if (highlightField.Key == "title")
                {
                    foreach (var highlight in highlightField.Value)
                    {
                        hit.Source.Title = highlight.ToString();
                    }
                }
            }
        }
    
        return View(search.Documents);
    }
    

    聚合查询

    var searchResponse = await client.SearchAsync<Person>(s => s
        .Size(0)
        .Query(q => q
             .Match(m => m
                .Field(f => f.FirstName)
                .Query("许嵩")
             )
        )
        .Aggregations(a => a
            .Terms("last_names", ta => ta
                .Field(f => f.LastName)
            )
        )
    );
    
    var termsAggregation = searchResponse.Aggregations.Terms("last_names");
    

    结构化: 特点,查询结果要么是true要么是false

    结构化一般查找时间,数字或者标题之类的,查询的答案始终是或否;文档是查询的匹配项,或者不是。

    开始时间在2017年之间的所有数据

    var searchResponse = _client.Search<Project>(s => s
        .Query(q => q
            .DateRange(r => r
                .Field(f => f.StartTime)
                .GreaterThanOrEquals(new DateTime(2017, 01, 01))
                .LessThan(new DateTime(2018, 01, 01))
            )
        )
    );
    
    {
      "query": {
        "range": {
          "startedOn": {
            "lt": "2018-01-01T00:00:00",
            "gte": "2017-01-01T00:00:00"
          }
        }
      }
    }
    

    非结构化搜索: 特点,在全文字段中搜索

    我们常用的搜索就是非结构化搜索,例如我搜一个人名

    var searchResponse = _client.Search<Project>(s => s
        .Query(q => q
            .Match(m => m
                .Field(f => f.Name)
                .Query("许嵩")
            )
        )
    );
    

    组合查询

    查找姓是 许 名是嵩的,并且时间必须在2017年

    var searchResponse = _client.Search<Project>(s => s
        .Query(q => q
            .Bool(b => b
                .Must(mu => mu
                    .Match(m => m 
                        .Field(f => f.FirstName)
                        .Query("许")
                    ), mu => mu
                    .Match(m => m 
                        .Field(f => f.LastName)
                        .Query("嵩")
                    )
                )
                .Filter(fi => fi
                     .DateRange(r => r
                        .Field(f => f.StartedOn)
                        .GreaterThanOrEquals(new DateTime(2017, 01, 01))
                        .LessThan(new DateTime(2018, 01, 01)) 
                    )
                )
            )
        )
    );
    
    {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "leadDeveloper.firstName": {
                  "query": "Russ"
                }
              }
            },
            {
              "match": {
                "leadDeveloper.lastName": {
                  "query": "Cam"
                }
              }
            }
          ],
          "filter": [
            {
              "range": {
                "startedOn": {
                  "lt": "2018-01-01T00:00:00",
                  "gte": "2017-01-01T00:00:00"
                }
              }
            }
          ]
        }
      }
    }
    

    还有一个更好用的写法

    searchResponse = _client.Search<Project>(s => s
        .Query(q => q
            .Match(m => m
                .Field(f => f.FirstName)
                .Query("许")
            ) && q 
            .Match(m => m
                .Field(f => f.LastName)
                .Query("嵩")
            ) && +q 
            .DateRange(r => r
                .Field(f => f.StartedOn)
                .GreaterThanOrEquals(new DateTime(2017, 01, 01))
                .LessThan(new DateTime(2018, 01, 01))
            )
        )
    );
    

    组合记得使用 +

    布尔查询

    不好的写法

    var searchResults = this.Client.Search<Project>(s => s
        .Query(q => q
            .Bool(b => b
                .Should(
                    bs => bs.Term(p => p.Name, "x"),
                    bs => bs.Term(p => p.Name, "y")
                )
            )
        )
    );
    

    这种写法很不好,如果很多bool嵌套查询,多个bool查询,结果是啥?结果就会像下图一样

    你的代码会变成凹陷缩进的样子,很丑,而且不利于维护,看着就头大了

    推荐使用的bool查询

    var firstSearchResponse = client.Search<Project>(s => s
        .Query(q => q
            .Term(p => p.Name, "x") || q
            .Term(p => p.Name, "y")
        )
    );
    
    var firstSearchResponse = client.Search<Project>(s => s
        .Query(q => q
            .Term(p => p.Name, "x") && q
            .Term(p => p.Name, "y")
        )
    );
    
    var firstSearchResponse = client.Search<Project>(s => s
        .Query(q => !q
            .Term(p => p.Name, "x")
        )
    );
    

    选择要返回的字段

    我们查询不需要所有的字段,只需要几个字段就可以

    查询全部的数据,但是只要Name和StartTime这两个字段

    var searchResponse = _client.Search<Project>(s => s
        .StoredFields(sf => sf
            .Fields(
                f => f.Name,
                f => f.StartTime
            )
        )
        .Query(q => q
            .MatchAll()
        )
    );
    

    源筛选

    var searchResponse = _client.Search<Project>(s => s
        .Source(sf => sf
            .Includes(i => i    //包括以下字段
                .Fields(
                    f => f.Name,
                    f => f.StartedOn
                )
            )
            .Excludes(e => e 
                .Fields("num*")   //排除其他字段
            )
        )
        .Query(q => q
            .MatchAll()
        )
    );
    
  • 相关阅读:
    一种C#读写二进制文件的通用方法
    关于POP3协议的一点资料
    关于看图工具的几点想法
    在WPF程序中将控件所呈现的内容保存成图像
    Nuget挂了的解决方法
    VisualStudio 2012中的单元测试
    在Andorid平板上体验Windows8的猜想
    创建自己的awaitable类型
    【转载】:最佳注释
    百度云盘试用
  • 原文地址:https://www.cnblogs.com/yunquan/p/12934209.html
Copyright © 2011-2022 走看看