一包煙的時間輕鬆學會.NET Core操作ElasticSearch 7

在互聯網上,隨處可見的搜索框。背後所用的技術大多數就是全文檢索。
在全文檢索領域,常見的庫/組件有:Lucene、Solr、Sphinx、ElasticSearch等。

簡單對比幾種全文引擎的區別

  • Lucene是一個基於Java開發的全文檢索基礎包,使用起來繁雜,且默認不支持分佈式檢索
  • Solr是基於Lucene開發的一個搜索工具。抽象度更高,使用更簡單,且提供一個控制面板。
  • ElasticSearch也是基於Lucene開發的。同樣是高度抽象,並提供了一個非常強大的DSL檢索功能,可以很方便的檢索出數據。
  • Solr和ES的區別主要在於:ES有強大的實時檢索能力而不怎麼掉速,Solr創建索引的同時,檢索速度會下降。如果不考慮實時檢索,Solr的速度更快。Solr社區更成熟。ES使用更方便更現代化。
  • Sphinx是俄羅斯人開發的一個全文檢索引擎,使用C++開發。性能比Java開發的es和solr高,但是在社區繁榮度上,比ES和solr差很多。比如中文分詞器,sphinx的coreseek插件已經停更了。sphinx有個非常好的地方就是可以作爲MySQL插件使用。

環境搭建

隨着容器化的發展,我們大部分環境都切換到Docker上了。本篇博文的環境通過Docker搭建。

ES在Docker中搭建

我使用的是ES7.4.2

docker run --name es -d  -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "ES_JAVA_OPTS=-Xms128m -Xmx128m" -v d:/elasticsearch/es7.4.2/data:/usr/share/elasticsearch/data -v d:/elasticsearch/es7.4.2/plugins:/usr/share/elasticsearch/plugins elasticsearch:7.4.2

我這裏把Docker中的es數據目錄和插件目錄映射到本機,方便操作。實際線上部署也應該映射數據目錄到宿主機,防止數據丟失。

搭建Kibana可視化環境。

docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.31.115:9200 -p 5601:5601 -e "I18N_LOCALE=zh-CN" -d kibana:7.4.2

運行成功後,在Docker控制面板上,就可以看到兩個正在運行的容器了。

在本機瀏覽器訪問 http://localhost:5601/ 即可打開Kibana儀表盤。

ElasticSearch基本概念

用數據庫的概念來對比ES的概念

數據庫 ElasticSearch
database 庫 index 索引
table 表 type 類型 7.x已經廢除
row 行 document 文檔
column 列 field 字段
chema 表結構 mapping 映射
SQL DSL
select GET
update PUT
delete delete

上手ElasticSearch的DSL

ES有兩種方式操作:1.url方式,2.http請求中的body提交json dsl

創建一個索引

PUT /qingcheng

刪除一個索引

DELETE /qingcheng

創建mapping

PUT /qingcheng
{
  "mappings": {
    "properties": {
      "name": {
        "type": "text"
      },
      "age": {
        "type": "integer"
      },
      "createtime": {
        "type": "date"
      }
    }
  }
}

響應

{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "qingcheng"
}



在ES7中已經不支持映射mapping的時候,指定_doc名稱了。ES會給一個默認的_doc名稱

新增字段

PUT /qingcheng/_mapping
{
  "properties":{
    "sex":{
      "type":"integer"
    }
  }
}

在ES中只能新增字段,無法修改已有字段。如果需要需改已有字段,只能重新創建索引,然後使用reindex遷移數據到新的索引。

查看索引

GET /qingcheng/_mapping

結果
{
  "qingcheng" : {
    "mappings" : {
      "properties" : {
        "age" : {
          "type" : "integer"
        },
        "createtime" : {
          "type" : "date"
        },
        "name" : {
          "type" : "text"
        },
        "sex" : {
          "type" : "integer"
        }
      }
    }
  }
}

插入以及數據

多次put同一個id到es,那就是更新了

POST /qingcheng/_doc/1
{
  "name":"青城",
  "age":30,
  "createtime":"2021-03-21",
  "sex":1
}

使用Post請求,在_doc的type中插入id爲1的一條數據。id可以自定義格式,可以爲數字以及自定義字符串

查看數據

GET /qingcheng/_doc/1

檢索數據

數據檢索的格式爲 GET /索引名稱/_search + json格式的body

基本搜索

GET /qingcheng/_search
{
  "query": {
    "query_string": {
      "default_field": "name",
      "query": "青城"
    }
  }
}

範圍搜索

GET /qingcheng/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 10,
        "lte": 50
      }
    }
  }
}

分頁搜索

GET /qingcheng/_search
{
  "query": {
    "match": {
      "name": "青"
    }
  }, 
  "from": 0,  //從多少條開始
  "size": 20  //取多少條
}

排序

GET /qingcheng/_search
{
  "sort": [
    {
      "age": {
        "order": "desc"
      }
    }
  ]
}

複雜搜索

在ES搜索中,一般會存在多個條件,類似於sql的and or等操作。在ES中使用bool操作來連接多個條件,must 必須滿足,should:滿足最好,不滿足也沒關係(如果滿足,es的搜索評分會更高,結果更靠前)

GET /qingcheng/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "青"
          }
        },
        {
          "range": {
            "age": {
              "gte": 10,
              "lte": 50
            }
          }
        }
      ],
      "should": [
        {
          "range": {
            "age": {
              "gte": 10,
              "lte": 50
            }
          }
        }
      ]
    }
  }
}

聚合

在ES中,聚合使用eggs來操作。可快速求出最大、平均、等值。

GET /qingcheng/_search
{
  "aggs": {
    "平均值": {
      "avg": {
        "field": "age"
      }
    }
  }
}

配置中文分詞器

ES默認的分詞器是中文分詞是按單個漢字分割。所以使用起來搜索結果不太準確。在ES的分詞插件中,中文分詞用的比較多的是IK分詞器

github地址:https://github.com/medcl/elasticsearch-analysis-ik

下載好ES對應版本的插件,解壓出來,放到ES的插件目錄。重啓ES,即可啓用插件。

我們對比一下使用ES默認分詞器和IK分詞器的結果

默認分詞器

使用IK分詞器

IK分詞器支持兩種分詞模式 1. ik_smart 2.ik_max_word

  • ik_smart模式

  • ik_max_word

兩種分詞模式的區別在於分詞粒度的粗細問題。而standard分詞直接按單個字符分割。

使用.NET Core的NEST客戶端

ES的.NET客戶端分爲兩個,一個是ElasticSearch.NET一個是NEST,NEST是高級的客戶端庫,提供更符合.NET程序員的操作api。ElasticSearch.NET更適合喜歡寫DSL的程序員。一般我們都使用NEST。

創建索引

[ElasticsearchType(RelationName = "estest")]
    class ESTest
    {
        [Number(NumberType.Integer, Name = "id")]
        public int Id { get; set; }

        [Text(Name = "name")]
        public string Name { get; set; }

        [Number(NumberType.Integer, Name = "age")]
        public int Age { get; set; }

        [Text(Name = "info", Analyzer = "ik_smart")]
        public string Info { get; set; }

        [Date(Name = "createtime", Format = "yyyy-MM-dd||yyyy-MM-dd HH:mm:ss")]
        public DateTime CreateTime { get; set; }
    }

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

            //創建索引
            var resp = client.Indices.Create("test", opt =>
           {
               return opt.Map<ESTest>(m => m.AutoMap());
           });
            Console.WriteLine("創建索引結果:" + resp.Acknowledged);
            Console.WriteLine(resp.DebugInformation);

插入數據

 var model = new ESTest()
            {
                Name = "青城1",
                Age = 20,
                Info = "順其自然,不代表我們可以不努力,而是努力之後有勇氣接受成敗。",
                Id = 2,
                CreateTime = DateTime.Now
            };

            var indexResp = client.Index(model, i => i.Index("test"));
            if (indexResp.IsValid)
            {

            }

檢索數據

 var res = client.Search<ESTest>(a => a.Index("test")
            .Query(a =>
                a.Match(m =>
                    m.Field(f => f.Info).Query("順其自然"))));
            foreach (var item in res.Documents)
            {
                Console.WriteLine(item.Name + " " + item.Info);
            }

檢索數據的寫法基本上和DSL語法結構一致。學會DSL,用C#也可以寫出正確的查詢語句。

學會以上的基本操作,就可以算是對ES有一個基本的瞭解了。更多深入的知識點可以去ES官方文檔學習。

NEST庫地址:https://github.com/elastic/elasticsearch-net

官方文檔:https://www.elastic.co/guide/en/elasticsearch/client/net-api/current/introduction.html


歡迎關注我的微信搜索公衆號 【青城同學】 ,當然也可以掃描下方的二維碼關注我

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章