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()
    )
);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM