ElasticSearch入門及進階實戰(1) 基礎入門

 

簡介

什麼是elasticsearch?

    elasticsearch是開源的分佈式、Restfull  風格的數據搜索與分析引擎,是時下最流行的全文搜索引擎。

elasticsearch和Apache Lucene

    Apache Lucene是時下最先進、高性能、全功能的搜索引擎庫,Apache Lucene原理和實現複雜。elasticsearch就是爲了解決Lucene複雜性的,elasticsearch基於Lucene,使用java語言開發,對Lucene做了一層封裝,提供一套簡單一致的Restfull 風格API,是的全文檢索更簡單。

elasticsearch不僅僅是全文搜索引擎:

  • 一個分佈式實時文檔存儲,每個字段都可以被索引和搜索。
  • 一個分佈式實時分析搜索引擎。
  • 支持上百個服務節點擴展,支持PB級的結構化數據和非結構化數據。

安裝運行

Windows下安裝

step1 安裝Kibana 下載Elasticsearch 6.2.2的zip包,並解壓到指定目錄,下載地址:https://www.elastic.co/cn/downloads/past-releases/elasticsearch-6-2-2
step2 安裝中文分詞插件,在elasticsearch-6.2.2\bin目錄下執行以下命令
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.2.2/elasticsearch-analysis-ik-6.2.2.zip
step3 啓動es  運行es安裝目錄/bin/elasticsearch.bat
step4 安裝Kibana  下載Kibana,作爲訪問Elasticsearch的客戶端,請下載6.2.2版本的zip包,並解壓到指定目錄,下載地址:https://artifacts.elastic.co/downloads/kibana/kibana-6.2.2-windows-x86_64.zip
step5 啓動Kibana  運行Kibana/bin/kibana.bat

linux下安裝

step1 下載elasticsearch 6.4.0的docker鏡像;
docker pull elasticsearch:6.4.0
step2 修改虛擬內存區域大小,否則會因爲過小而無法啓動;
sysctl -w vm.max_map_count=262144
step3 修改該目錄的權限,使es有權訪問目錄
chmod 777 /mydata/elasticsearch/data/
step4 使用docker命令啓動;
docker run -p 9200:9200 -p 9300:9300 --name elasticsearch \
-e "discovery.type=single-node" \
-e "cluster.name=elasticsearch" \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-d elasticsearch:6.4.0
step5 安裝中文分詞器IKAnalyzer,並重新啓動;
docker exec -it elasticsearch /bin/bash
#此命令需要在容器中運行
#進入ES目錄
docker exec -it elasticsearch /bin/bash 
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.4.0/elasticsearch-analysis-ik-6.4.0.zip
docker restart elasticsearch
step6 訪問es測試安裝是否成功
http://linux服務器:9200/
step7 下載kibana 6.4.0的docker鏡像
step8 docker命令啓動
docker run --name kibana -p 5601:5601 \
--link elasticsearch:es \
-e "elasticsearch.hosts=http://es:9200" \
-d kibana:6.4.0
step8 訪問測試安裝是否成功
http://linux服務器地址:5601

Kibana是es可視化用戶界面,在DevTol下可以使用es DSL語言操縱ES。

elasticsearch基本概念

全文搜索(Full-Text Search):計算機檢索程序通過掃描文章每一個詞,對每一個詞建立索引,指明該詞在文章中出現次數和位置。當用戶查詢時,檢索程序根據事先建立的索引進行查詢並返回查詢結果給用戶的查詢方式。

倒排索引(Inverted Index):

  • 該索引表中每一項都包括一個屬性值和具有該屬性值的各記錄的地址;
  • 該索引表不是由記錄確認屬性值,而是由屬性值來確定記錄的位置,因此成爲倒排索引;
  • elasticsearch能夠實現高效、快速搜索功能,正是基於倒排索引。

節點 &集羣(Node & Cluster):elasticsearch本質是分佈式數據庫,允許多臺服務器共同工作。每臺服務器可以運行多個es實例,單個實例就是節點(Node),一組節點構成集羣(Cluster)。

索引(Index):elasticsearch管理數據的頂層單位,Index必須小寫英文命名。Index相當於關係數據庫中的數據庫。

文檔(Document):Index中的單條記錄稱爲Document,Document使用JSON格式表示。同一個Index下Document不要求具有相同數據結構(Scheme),但是最好保持一致,這樣可以提供搜索效率。

類型(Type):

  • Document可以分組,比如Order這個Index,可以按訂單狀態分組,可以按訂單類型分組,這個分組稱爲Type。
  • elasticsearch Tyoe是虛擬邏輯分組,用來過濾Document,Type相當於關係數據庫中的數據表;
  • 一個Index下不同Type應該有相似結構,完全不同數據結構的數據應該建立不同Index。

文檔元數據:文檔元數據可以分爲三部分

  • _index: 文檔存放位置
  • -Type: 文檔類型
  • _id: 文檔唯一標識

三者可以唯一表示一個文檔。

字段:Document是一個JSON數據結構,包含許多字段,每個字段都有對應值。字段相當於關係數據庫中的字段。

                                                                      es和關係數據庫類比圖

elasticsearch入門

elasticsearch交互方式

elasticsearch提供Java API 和 Restfull API。基於Restfull API 其他語言程序可以通過9200端口和es進行通訊。

elasticsearch 請求分析

部件 說明
VERB 適當的HTTP方法或謂詞:GET\PUT\DELETE\POST\HEAD。
PROTOCOL http或https(如果elasticsearch前面啓用了代理)
HOST elasticsearch集羣中任一節點主機名或者用localhost代表本地節點
PORT elasticsearch端口號,默認9200
PATH API終端路徑(如_count將返回集羣中文檔數量)。PATH可能包含多個組件,例如:_cluster/stats 和 _nodes/stats/jvm
QUERY_STRING 任意可選的查詢字符串參數,例如:?pretty 將格式化地輸出 JSON 返回值,使其更容易閱讀
BODY 一個JSON格式請求體

 

 

 

 

 

 

 

HTTP方法說明

HTTP方法 說明
GET 獲取請求對象當前狀態
PUT 創建一個對象
POST 改變當前對象狀態
DELETE 刪除一個對象
HEAD 獲取對象的基礎信息

 

 

 

 

 

基礎命令詳解

查看集羣健康狀態:

GET /_cat/health?v

查看節點狀態:

GET /_cat/nodes?v

查看所有索引信息:

GET /_cat/indices?v

創建索引並查看;

PUT /customer
GET /_cat/indices?v

刪除索引並查看:

DELETE /customer
GET /_cat/indices?v

查看文檔的類型:

GET /pms/_mapping

在索引中添加文檔

PUT /customer/doc/1
{
  "name": "John Doe"
}

查看索引中的文檔

GET /customer/doc/1
{
  "_index": "customer",
  "_type": "doc",
  "_id": "1",
  "_version": 1,
  "found": true,
  "_source": {
    "name": "John Doe"
  }
}

修改索引中的文檔:

POST /customer/doc/1/_update
{
  "doc": { "name": "Jane Doe" }
}
{
  "_index": "customer",
  "_type": "doc",
  "_id": "1",
  "_version": 2,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 1,
  "_primary_term": 1
}
GET /customer/doc/1
{
  "_index": "customer",
  "_type": "doc",
  "_id": "1",
  "_version": 2,
  "found": true,
  "_source": {
    "name": "Jane Doe"
  }
}

刪除索引中文檔:

DELETE /customer/doc/1

對索引文檔進行批量操作

POST /customer/doc/_bulk
{"index":{"_id":"1"}}
{"name": "John Doe" }
{"index":{"_id":"2"}}
{"name": "Jane Doe" }

數據搜索

elasticsearch提供了豐富靈活的查詢語言-查詢表達式(Query DSL),支持構建更加複雜和健壯的查詢。

最簡單的搜索,使用match_all來表示,例如搜索全部:

GET /pms/_search
{
  "query": { "match_all": {} }
}

分頁搜索,from表示偏移量,從0開始,size表示每頁顯示的數量;

GET /pms/_search
{
  "query": { "match_all": {} },
  "from": 0,
  "size": 3
}

搜索排序,使用sort表示,例如按price字段降序排列;

GET /pms/_search
{
  "query": { "match_all": {} },
  "sort": { "price": { "order": "desc" } }
}

搜索並返回指定字段內容,使用_source表示,例如只返回nameprice兩個字段內容:

GET /pms/_search
{
  "query": { "match_all": {} },
  "_source": ["name", "price"]
}

條件搜索,使用match表示匹配條件,例如搜索出price98的文檔:

GET /pms/_search
{
  "query": {
    "match": {
      "price": 98
    }
  }
}

文本類型字段的條件搜索,例如搜索address字段中包含mill的文檔,對比上一條搜索可以發現,對於數值類型match操作使用的是精確匹配,對於文本類型使用的是模糊匹配:

GET /pms/_search
{
  "query": {
    "match": {
      "name": "海瀾之家"
    }
  },
  "_source": [
    "name",
    "subTitle"
  ]
}
{
  "took": 7,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 3,
    "max_score": 4.2882357,
    "hits": [
      {
        "_index": "pms",
        "_type": "product",
        "_id": "30",
        "_score": 4.2882357,
        "_source": {
          "subTitle": "2018夏季新品微彈舒適新款短T男生 6月6日-6月20日,滿300減30,參與互動贏百元禮券,立即分享贏大獎",
          "name": "HLA海瀾之家簡約動物印花短袖T恤"
        }
      },
      {
        "_index": "pms",
        "_type": "product",
        "_id": "32",
        "_score": 4.2882357,
        "_source": {
          "subTitle": "HLA海瀾之家短袖T恤男基礎款簡約圓領HNTBJ2E153A藏青(F3)175/92A(50)",
          "name": "HLA海瀾之家短袖T恤男基礎款"
        }
      },
      {
        "_index": "pms",
        "_type": "product",
        "_id": "31",
        "_score": 3.8090763,
        "_source": {
          "subTitle": "2018夏季新品短袖T恤男HNTBJ2E080A 藍灰花紋80 175/92A/L80A 藍灰花紋80 175/92A/L",
          "name": "HLA海瀾之家藍灰花紋圓領針織布短袖T恤"
        }
      }
    ]
  }
}

組合搜索

組合搜索,使用bool來進行組合,must表示同時滿足,例如搜索subTitle字段中同時包含2018男生的文檔;

GET /pms/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "subTitle": "2018" } },
        { "match": { "subTitle": "男生" } }
      ]
    }
  }
}

組合搜索,should表示滿足其中任意一個,搜索name字段中包含HLA或者海瀾之家的文檔

GET /pms/_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "name": "HLA" } },
        { "match": { "name": "海瀾之家" } }
      ]
    }
  }
}

組合搜索,must_not表示不同時滿足,搜索subTitle字段不同時包含移動 電信的文檔

GET /pms/_search
{
  "query": {
    "bool": {
      "must_not": [
        { "match": { "subTitle": "移動" } },
        { "match": { "subTitle": "電信" } }
      ]
    }
  }
}

組合搜索,must和must_not配合,搜索name包含小米subTitle不包含電信的文檔

GET /pms/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "name": "小米" } }
      ],
      "must_not": [
        { "match": { "subTitle": "電信" } }
      ]
    }
  }
}

過濾搜索

使用filter來表示,比如獲取price在600-1000之間的商品

GET /pms/_search
{
  "query": {
    "bool": {
      "must": { "match_all": {} },
      "filter": {
        "range": {
          "price": {
            "gte": 600,
            "lte": 1000
          }
        }
      }
    }
  }
}

搜索聚合

對搜索結果進行聚合,用aggs表示,類似sql的group by 。例如對brandName進行聚合,統計出brandName相同的數目

GET /pms/_search
{
  "size": 0,
  "aggs": {
    "group_by_brandName": {
      "terms": {
        "field": "brandName"
      }
    }
  }
}
{
  "took": 90,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 11,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "group_by_brandName": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "小米",
          "doc_count": 4
        },
        {
          "key": "海瀾之家",
          "doc_count": 3
        },
        {
          "key": "NIKE",
          "doc_count": 2
        },
        {
          "key": "華爲",
          "doc_count": 1
        },
        {
          "key": "蘋果",
          "doc_count": 1
        }
      ]
    }
  }
}

嵌套聚合,同時聚合brandName和price,計算出brandName相同的數目和price的平均值

GET /pms/_search
{
  "size": 0,
  "aggs": {
    "group_by_brandName": {
      "terms": {
        "field": "brandName"
      },
      "aggs": {
        "average_price": {
          "avg": {
            "field": "price"
          }
        }
      }
    }
  }
}
{
  "took": 123,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 11,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "group_by_brandName": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "小米",
          "doc_count": 4,
          "average_price": {
            "value": 2461.5
          }
        },
        {
          "key": "海瀾之家",
          "doc_count": 3,
          "average_price": {
            "value": 88
          }
        },
        {
          "key": "NIKE",
          "doc_count": 2,
          "average_price": {
            "value": 434
          }
        },
        {
          "key": "華爲",
          "doc_count": 1,
          "average_price": {
            "value": 3788
          }
        },
        {
          "key": "蘋果",
          "doc_count": 1,
          "average_price": {
            "value": 5499
          }
        }
      ]
    }
  }
}

對聚合搜索的結果進行排序

GET /pms/_search
{
  "size": 0,
  "aggs": {
    "group_by_brandName": {
      "terms": {
        "field": "brandName",
        "order": {
          "average_price": "desc"
        }
      },
      "aggs": {
        "average_price": {
          "avg": {
            "field": "price"
          }
        }
      }
    }
  }
}
{
  "took": 39,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 11,
    "max_score": 0,
    "hits": []
  },
  "aggregations": {
    "group_by_brandName": {
      "doc_count_error_upper_bound": 0,
      "sum_other_doc_count": 0,
      "buckets": [
        {
          "key": "蘋果",
          "doc_count": 1,
          "average_price": {
            "value": 5499
          }
        },
        {
          "key": "華爲",
          "doc_count": 1,
          "average_price": {
            "value": 3788
          }
        },
        {
          "key": "小米",
          "doc_count": 4,
          "average_price": {
            "value": 2461.5
          }
        },
        {
          "key": "NIKE",
          "doc_count": 2,
          "average_price": {
            "value": 434
          }
        },
        {
          "key": "海瀾之家",
          "doc_count": 3,
          "average_price": {
            "value": 88
          }
        }
      ]
    }
  }
}

參考 https://mp.weixin.qq.com/s/cohWZy_eUOUqbmUxhXzzNA

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