es的使用與原理11 -- 初識(shí)es及es簡(jiǎn)單CRUD語(yǔ)法

為什么不能使用數(shù)據(jù)庫(kù)做搜索?

1、比方說(shuō),每條記錄的指定字段的文本,可能會(huì)很長(zhǎng),比如說(shuō)“商品描述”字段的長(zhǎng)度,有長(zhǎng)達(dá)數(shù)千個(gè),甚至數(shù)萬(wàn)個(gè)字符,這個(gè)時(shí)候,每次都要對(duì)每條記錄的所有文本進(jìn)行掃描。
你包不包含我指定的這個(gè)關(guān)鍵詞(比如說(shuō)“牙膏”)
2、還不能將搜索詞拆分開(kāi)來(lái),盡可能去搜索更多的符合你的期望的結(jié)果,比如輸入“生化機(jī)”,就搜索不出來(lái)“生化危機(jī)”
總的來(lái)說(shuō)就是數(shù)據(jù)庫(kù)來(lái)實(shí)現(xiàn)搜索,是不太靠譜的。通常來(lái)說(shuō),性能會(huì)很差的。
另外:
(1)數(shù)據(jù)量較大,es的分布式本質(zhì),可以幫助你快速進(jìn)行擴(kuò)容,承載大量數(shù)據(jù)
(2)數(shù)據(jù)結(jié)構(gòu)靈活多變,隨時(shí)可能會(huì)變化,而且數(shù)據(jù)結(jié)構(gòu)之間的關(guān)系,非常復(fù)雜,如果我們用傳統(tǒng)數(shù)據(jù)庫(kù),那是不是很坑,因?yàn)橐媾R大量的表
(3)對(duì)數(shù)據(jù)的相關(guān)操作,較為簡(jiǎn)單,比如就是一些簡(jiǎn)單的增刪改查,用我們之前講解的那些document操作就可以搞定
(4)NoSQL數(shù)據(jù)庫(kù),適用的也是類似于上面的這種場(chǎng)景

什么是全文檢索和Lucene?
image.png

lucene,就是一個(gè)jar包,里面包含了封裝好的各種建立倒排索引,以及進(jìn)行搜索的代碼,包括各種算法。我們就用java開(kāi)發(fā)的時(shí)候,引入lucene jar,然后基于lucene的api進(jìn)行去進(jìn)行開(kāi)發(fā)就可以了。
用lucene,我們就可以去將已有的數(shù)據(jù)建立索引,lucene會(huì)在本地磁盤上面,給我們組織索引的數(shù)據(jù)結(jié)構(gòu)。另外的話,我們也可以用lucene提供的一些功能和api來(lái)針對(duì)磁盤上進(jìn)行操作和查詢。

什么是Elasticsearch?
image.png
Elasticsearch的功能,干什么的

(1)分布式的搜索引擎和數(shù)據(jù)分析引擎

搜索:百度,網(wǎng)站的站內(nèi)搜索,IT系統(tǒng)的檢索
數(shù)據(jù)分析:電商網(wǎng)站,最近7天牙膏這種商品銷量排名前10的商家有哪些;新聞網(wǎng)站,最近1個(gè)月訪問(wèn)量排名前3的新聞版塊是哪些
分布式,搜索,數(shù)據(jù)分析

(2)全文檢索,結(jié)構(gòu)化檢索,數(shù)據(jù)分析

全文檢索:我想搜索商品名稱包含牙膏的商品,select * from products where product_name like "%牙膏%"
結(jié)構(gòu)化檢索:我想搜索商品分類為日化用品的商品都有哪些,select * from products where category_id='日化用品'
部分匹配、自動(dòng)完成、搜索糾錯(cuò)、搜索推薦
數(shù)據(jù)分析:我們分析每一個(gè)商品分類下有多少個(gè)商品,select category_id,count(*) from products group by category_id

(3)對(duì)海量數(shù)據(jù)進(jìn)行近實(shí)時(shí)的處理

分布式:ES自動(dòng)可以將海量數(shù)據(jù)分散到多臺(tái)服務(wù)器上去存儲(chǔ)和檢索
海聯(lián)數(shù)據(jù)的處理:分布式以后,就可以采用大量的服務(wù)器去存儲(chǔ)和檢索數(shù)據(jù),自然而然就可以實(shí)現(xiàn)海量數(shù)據(jù)的處理了
近實(shí)時(shí):檢索個(gè)數(shù)據(jù)要花費(fèi)1小時(shí)(這就不要近實(shí)時(shí),離線批處理,batch-processing);在秒級(jí)別對(duì)數(shù)據(jù)進(jìn)行搜索和分析

跟分布式/海量數(shù)據(jù)相反的:lucene,單機(jī)應(yīng)用,只能在單臺(tái)服務(wù)器上使用,最多只能處理單臺(tái)服務(wù)器可以處理的數(shù)據(jù)量

elasticsearch的核心概念

(1)Near Realtime(RT):近實(shí)時(shí),數(shù)據(jù)被寫入到es 到可以被搜索到這個(gè)時(shí)間 在一秒內(nèi)可以完成。

(2)Cluster:集群,包含多個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)屬于哪個(gè)集群是通過(guò)一個(gè)配置(集群名稱,默認(rèn)是elasticsearch)來(lái)決定的,對(duì)于中小型應(yīng)用來(lái)說(shuō),剛開(kāi)始一個(gè)集群就一個(gè)節(jié)點(diǎn)很正常
(3)Node:節(jié)點(diǎn),集群中的一個(gè)節(jié)點(diǎn),節(jié)點(diǎn)也有一個(gè)名稱(默認(rèn)是隨機(jī)分配的),節(jié)點(diǎn)名稱很重要(在執(zhí)行運(yùn)維管理操作的時(shí)候),默認(rèn)節(jié)點(diǎn)會(huì)去加入一個(gè)名稱為“elasticsearch”的集群,如果直接啟動(dòng)一堆節(jié)點(diǎn),那么它們會(huì)自動(dòng)組成一個(gè)elasticsearch集群,當(dāng)然一個(gè)節(jié)點(diǎn)也可以組成一個(gè)elasticsearch集群
(4)Document&field:文檔,es中的最小數(shù)據(jù)單元,一個(gè)document可以是一條客戶數(shù)據(jù),一條商品分類數(shù)據(jù),一條訂單數(shù)據(jù),通常用JSON數(shù)據(jù)結(jié)構(gòu)表示,
每個(gè)index下的type中,都可以去存儲(chǔ)多個(gè)document。一個(gè)document里面有多個(gè)field,每個(gè)field就是一個(gè)數(shù)據(jù)字段。
product document

{
  "product_id": "1",
  "product_name": "高露潔牙膏",
  "product_desc": "高效美白",
  "category_id": "2",
  "category_name": "日化用品"
}

(5)Index:索引,包含一堆有相似結(jié)構(gòu)的文檔數(shù)據(jù),比如可以有一個(gè)客戶索引,商品分類索引,訂單索引,索引有一個(gè)名稱。一個(gè)index包含很多document,一個(gè)index就代表了一類類似的或者相同的document。比如說(shuō)建立一個(gè)product index,商品索引,里面可能就存放了所有的商品數(shù)據(jù),所有的商品document。
(6)Type:類型,每個(gè)索引里都可以有一個(gè)或多個(gè)type,type是index中的一個(gè)邏輯數(shù)據(jù)分類,一個(gè)type下的document,都有相同的field,比如博客系統(tǒng),有一個(gè)索引,可以定義用戶數(shù)據(jù)type,博客數(shù)據(jù)type,評(píng)論數(shù)據(jù)type。
type,日化商品type,電器商品type,生鮮商品type

日化商品type:product_id,product_name,product_desc,category_id,category_name
電器商品type:product_id,product_name,product_desc,category_id,category_name,service_period
生鮮商品type:product_id,product_name,product_desc,category_id,category_name,eat_period

每一個(gè)type里面,都會(huì)包含一堆document,類型于數(shù)據(jù)庫(kù)中,這里的每一行數(shù)據(jù)就是一個(gè)document,

{
  "product_id": "2",
  "product_name": "長(zhǎng)虹電視機(jī)",
  "product_desc": "4k高清",
  "category_id": "3",
  "category_name": "電器",
  "service_period": "1年"
}
{
  "product_id": "3",
  "product_name": "基圍蝦",
  "product_desc": "純天然,冰島產(chǎn)",
  "category_id": "4",
  "category_name": "生鮮",
  "eat_period": "7天"
}

(7)shard:?jiǎn)闻_(tái)機(jī)器無(wú)法存儲(chǔ)大量數(shù)據(jù),es可以將一個(gè)索引中的數(shù)據(jù)切分為多個(gè)shard,分布在多臺(tái)服務(wù)器上存儲(chǔ)。有了shard就可以橫向擴(kuò)展,存儲(chǔ)更多數(shù)據(jù),讓搜索和分析等操作分布到多臺(tái)服務(wù)器上去執(zhí)行,提升吞吐量和性能。每個(gè)shard都是一個(gè)lucene index。
(8)replica:任何一個(gè)服務(wù)器隨時(shí)可能故障或宕機(jī),此時(shí)shard可能就會(huì)丟失,因此可以為每個(gè)shard創(chuàng)建多個(gè)replica副本。replica可以在shard故障時(shí)提供備用服務(wù),保證數(shù)據(jù)不丟失,多個(gè)replica還可以提升搜索操作的吞吐量和性能。primary shard(建立索引時(shí)一次設(shè)置,不能修改,默認(rèn)5個(gè)),replica shard(隨時(shí)修改數(shù)量,默認(rèn)1個(gè)),默認(rèn)每個(gè)索引10個(gè)shard,5個(gè)primary shard,5個(gè)replica shard,最小的高可用配置,是2臺(tái)服務(wù)器。


image.png
elasticsearch核心概念 vs. 數(shù)據(jù)庫(kù)核心概念
Elasticsearch 數(shù)據(jù)庫(kù)
Index 庫(kù)
Type
Document
Filed
windows 下使用es

先安裝java環(huán)境,至少JDK1.8,分別下載解壓 elasticsearch-5.2.0.zip,kibana-5.2.0-windows-x86.zip,進(jìn)入到各自bin目錄下,啟動(dòng)elasticsearch.bat,kibana.bat腳本,
檢驗(yàn)是否啟動(dòng)成功http://localhost:9200/?pretty
http://localhost:5601/

es中的數(shù)據(jù)與關(guān)系型db中的數(shù)據(jù)

對(duì)象數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫(kù)中,只能拆解開(kāi)來(lái),變?yōu)楸馄降亩鄰埍?,每次查詢的時(shí)候還得還原回對(duì)象格式,相當(dāng)麻煩。ES是面向文檔的,文檔中存儲(chǔ)的數(shù)據(jù)結(jié)構(gòu),與面向?qū)ο蟮臄?shù)據(jù)結(jié)構(gòu)是一樣的,基于這種文檔數(shù)據(jù)結(jié)構(gòu),es可以提供復(fù)雜的索引,全文檢索,分析聚合等功能
如以下es 中的數(shù)據(jù)

{
    "email":      "zhangsan@sina.com",
    "first_name": "san",
    "last_name": "zhang",
    "info": {
        "bio":         "curious and modest",
        "age":         30,
        "interests": [ "bike", "climb" ]
    },
    "join_date": "2017/01/01"
}

es存儲(chǔ)的數(shù)據(jù)基本與客戶端提交上來(lái)的面向?qū)ο髷?shù)據(jù)一致,但是假設(shè)我們將這個(gè)數(shù)據(jù)持久化到mysql中,我們需要建立兩張表 然后用一個(gè)字段來(lái)關(guān)聯(lián)起來(lái)。

es API
  • cat api
    GET /_cat/health?v

如何快速了解集群的健康狀況?green、yellow、red?
green:每個(gè)索引的primary shard和replica shard都是active狀態(tài)的
yellow:每個(gè)索引的primary shard都是active狀態(tài)的,但是部分replica shard不是active狀態(tài),處于不可用的狀態(tài)
red:不是所有索引的primary shard都是active狀態(tài)的,部分索引有數(shù)據(jù)丟失了

  • 快速查看集群中有哪些索引
    GET /_cat/indices?v
health status index   uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   .kibana Sonk96QMSgmP7seyOVhx8A   1   1          1            0      3.1kb          3.1kb
  • (1)新增商品:新增文檔,建立索引。 es會(huì)自動(dòng)建立index和type,不需要提前創(chuàng)建,而且es默認(rèn)會(huì)對(duì)document每個(gè)field都建立倒排索引,讓其可以被搜索
    語(yǔ)法:
    PUT /index/type/id
    {
    "json數(shù)據(jù)"
    }
PUT /ecommerce/product/1
{
    "name" : "gaolujie yagao",
    "desc" :  "gaoxiao meibai",
    "price" :  30,
    "producer" :      "gaolujie producer",
    "tags": [ "meibai", "fangzhu" ]
}
// 返回以下數(shù)據(jù)
{
  "_index": "ecommerce",
  "_type": "product",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": true
}
  • (2)查詢商品:檢索文檔
    語(yǔ)法: GET /index/type/id
GET /ecommerce/product/1

{
  "_index": "ecommerce",
  "_type": "product",
  "_id": "1",
  "_version": 1,
  "found": true,
  "_source": {
    "name": "gaolujie yagao",
    "desc": "gaoxiao meibai",
    "price": 30,
    "producer": "gaolujie producer",
    "tags": [
      "meibai",
      "fangzhu"
    ]
  }
}
  • (3)修改商品:替換文檔
PUT /ecommerce/product/1
{
    "name" : "jiaqiangban gaolujie yagao",
    "desc" :  "gaoxiao meibai",
    "price" :  30,
    "producer" :      "gaolujie producer",
    "tags": [ "meibai", "fangzhu" ]
}

修改數(shù)據(jù)的時(shí)候 用這種方式,有一個(gè)容易出業(yè)務(wù) bug 的地方是 其他字段會(huì)被清空。如下面的命令執(zhí)行之后 這個(gè)數(shù)據(jù)就只剩下name 這一個(gè)filed了,其他沒(méi)了。修改數(shù)據(jù)主post會(huì)比較好一點(diǎn)

PUT /ecommerce/product/1
{
    "name" : "jiaqiangban gaolujie yagao"
}
  • (4)修改商品:更新文檔 (推薦),也叫 partial update 語(yǔ)法
POST /ecommerce/product/1/_update
{
  "doc": {
    "name": "jiaqiangban gaolujie yagao"
  }
}
  • (5)刪除商品:刪除文檔
    語(yǔ)法 DELETE /ecommerce/product/1
DELETE /ecommerce/product/1

{
  "found": true,
  "_index": "ecommerce",
  "_type": "product",
  "_id": "1",
  "_version": 9,
  "result": "deleted",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  }
}
多種搜索方式
  • 1、query string search --這種方式幾乎不會(huì)用
    搜索商品名稱中包含yagao的商品,而且按照售價(jià)降序排序:GET /ecommerce/product/_search?q=name:yagao&sort=price:desc
    query string search的由來(lái),因?yàn)閟earch參數(shù)都是以http請(qǐng)求的query string來(lái)附帶的
  • 2、query DSL , DSL:Domain Specified Language,特定領(lǐng)域的語(yǔ)言 --這種方式更好用
    查詢所有的商品
GET /ecommerce/product/_search
{
  "query": { "match_all": {} }
}

查詢名稱包含yagao的商品,同時(shí)按照價(jià)格降序排序

GET /ecommerce/product/_search
{
    "query" : {
        "match" : {
            "name" : "yagao"
        }
    },
    "sort": [
        { "price": "desc" }
    ]
}

分頁(yè)查詢商品,總共3條商品,假設(shè)每頁(yè)就顯示1條商品,現(xiàn)在顯示第2頁(yè),所以就查出來(lái)第2個(gè)商品

GET /ecommerce/product/_search
{
  "query": { "match_all": {} },
  "from": 1,
  "size": 1
}

不查詢所有列,指定特定的列 下面只查詢name和price列

GET /ecommerce/product/_search
{
  "query": { "match_all": {} },
  "_source": ["name", "price"]
}
  • 3、query filter
    搜索商品名稱包含yagao,而且售價(jià)大于25元的商品
GET /ecommerce/product/_search
{
    "query" : {
        "bool" : {
            "must" : {
                "match" : {
                    "name" : "yagao" 
                }
            },
            "filter" : {
                "range" : {
                    "price" : { "gt" : 25 } 
                }
            }
        }
    }
}
  • 4,full-text search(全文檢索)這里與之前的區(qū)別是"match" 內(nèi)的字段的值是兩個(gè)詞
GET /ecommerce/product/_search
{
    "query" : {
        "match" : {
            "producer" : "yagao producer"
        }
    }
}

producer 這個(gè)字段,會(huì)先被拆解,建立倒排索引
special 4
yagao 4
producer 1,2,3,4
gaoluie 1
zhognhua 3
jiajieshi 2
可以看出 最終的結(jié)果第一條肯定是4 因?yàn)?既包含yagao也包含producer

  • 5、phrase search(短語(yǔ)搜索)
    跟全文檢索相對(duì)應(yīng),相反,全文檢索會(huì)將輸入的搜索串拆解開(kāi)來(lái),去倒排索引里面去一一匹配,只要能匹配上任意一個(gè)拆解后的單詞,就可以作為結(jié)果返回
    phrase search,要求輸入的搜索串,必須在指定的字段文本中,完全包含一模一樣的,才可以算匹配,才能作為結(jié)果返回
GET /ecommerce/product/_search
{
    "query" : {
        "match_phrase" : {
            "producer" : "yagao producer"
        }
    }
}
  • 6、highlight search(高亮搜索結(jié)果)
GET /ecommerce/product/_search
{
    "query" : {
        "match" : {
            "producer" : "producer"
        }
    },
    "highlight": {
        "fields" : {
            "producer" : {}
        }
    }
}
嵌套聚合,下鉆分析,聚合分析
  • 1, 計(jì)算每個(gè)tag下的商品數(shù)量 根據(jù)tags字段分組顯示其數(shù)量
GET /ecommerce/product/_search
{
  "size": 0,
  "aggs": {
    "all_tags": {
      "terms": { "field": "tags" }
    }
  }
}
  • 2,對(duì)名稱中包含yagao的商品,計(jì)算每個(gè)tag下的商品數(shù)量 (先搜索再分析)
GET /ecommerce/product/_search
{
  "size": 0,
  "query": {
    "match": {
      "name": "yagao"
    }
  },
  "aggs": {
    "all_tags": {
      "terms": {
        "field": "tags"
      }
    }
  }
}
  • 3,先分組,再算每組的平均值,計(jì)算每個(gè)tag下的商品的平均價(jià)格
GET /ecommerce/product/_search
{
    "size": 0,
    "aggs" : {
        "group_by_tags" : {
            "terms" : { "field" : "tags" },
            "aggs" : {
                "avg_price" : {
                    "avg" : { "field" : "price" }
                }
            }
        }
    }
}
  • 4,計(jì)算每個(gè)tag下的商品的平均價(jià)格,并且按照平均價(jià)格降序排序
GET /ecommerce/product/_search
{
    "size": 0,
    "aggs" : {
        "all_tags" : {
            "terms" : { "field" : "tags", "order": { "avg_price": "desc" } },
            "aggs" : {
                "avg_price" : {
                    "avg" : { "field" : "price" }
                }
            }
        }
    }
}
  • 5,按照指定的價(jià)格范圍區(qū)間進(jìn)行分組,然后在每組內(nèi)再按照tag進(jìn)行分組,最后再計(jì)算每組的平均價(jià)格
GET /ecommerce/product/_search
{
  "size": 0,
  "aggs": {
    "group_by_price": {
      "range": {
        "field": "price",
        "ranges": [
          {
            "from": 0,
            "to": 20
          },
          {
            "from": 20,
            "to": 40
          },
          {
            "from": 40,
            "to": 50
          }
        ]
      },
      "aggs": {
        "group_by_tags": {
          "terms": {
            "field": "tags"
          },
          "aggs": {
            "average_price": {
              "avg": {
                "field": "price"
              }
            }
          }
        }
      }
    }
  }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容