零、提要
1.簡單的搜索方式:query string search
2.強大的搜索方式:query DSL
3.搜索中的過濾:query filter
4.全文搜索:full-text search
5.部分內容搜索:phrase search
6.高亮搜索:highlight search
一、準備
環境準備:
見上一篇《技.藝.道:elasticsearch概念梳理及基礎操作》
數據準備:
PUT /ecommerce/product/1
{
"name" : "gaolujie yagao",
"desc" : "gaoxiao meibai",
"price" : 30,
"producer" : "gaolujie producer",
"tags" : ["meibai","fangzhu"]
}
PUT /ecommerce/product/2
{
"name" : "jiajieshi yagao",
"desc" : "youxiao meibai",
"price" : 35,
"producer" : "gaolujie producer",
"tags" : ["meibai","fangzhu"]
}
PUT /ecommerce/product/3
{
"name" : "zhonghua yagao",
"desc" : "caoben meibai",
"price" : 20,
"producer" : "gaolujie producer",
"tags" : ["qingxin"]
}
PUT /ecommerce/product/4
{
"name":"heiren yagao",
"desc":"heiren meibai",
"price":50,
"producer":"heiren yagao producer",
"tags":["meibai"]
}
二、詳述
1.query string search
功能:實現簡單的條件搜索
基本語法:GET /yourindex/yourtype/_search
實例-搜索全部商品:GET /ecommerce/product/_search
條件查詢語法:GET /yourindex/yourtype/_search?q=name:yagao&sort=price:desc
實例-搜索name字段包含"yaogao"商品,結果按"price"字段倒序排列:GET /ecommerce/product/_search?q=name:yagao&sort=price:desc
查詢結果:
{
"took": 2,
"timed_out": false,
"_shards": {
"total": 5,
"successful": 5,
"failed": 0
},
"hits": {
"total": 3,
"max_score": 1,
"hits": [
{
"_index": "ecommerce",
"_type": "product",
"_id": "2",
"_score": 1,
"_source": {
"name": "jiajieshi yagao",
"desc": "youxiao meibai",
"price": 35,
"producer": "gaolujie producer",
"tags": [
"meibai",
"fangzhu"
]
}
},
{
"_index": "ecommerce",
"_type": "product",
"_id": "1",
"_score": 1,
"_source": {
"name": "good gaolujie yagao",
"desc": "gaoxiao meibai",
"price": 30,
"producer": "gaolujie producer",
"tags": [
"meibai",
"fangzhu"
]
}
},
{
"_index": "ecommerce",
"_type": "product",
"_id": "3",
"_score": 1,
"_source": {
"name": "zhonghua yagao",
"desc": "caoben meibai",
"price": 20,
"producer": "gaolujie producer",
"tags": [
"qingxin"
]
}
}
]
}
}
查詢結果說明:
- took:本次查詢耗時(毫秒)
- timed_out:是否超時,這裏是沒有
- _shards:數據拆成了5個分片,所以對於搜索請求,會發送至所有primary shard(或者是它的某個replica shard也可以)
- hits.total:查詢結果的數量,3個document。
- hits.hits:包好了匹配搜索的document的詳細數據。
2.query DSL(Domain Specified Language)
功能:實現複雜的條件搜索
查詢所有數據:
GET /ecommerce/product/_search
{
"query": {"match_all" : {} }
}
查詢“name”字段包含“yagao”的數據,結果按“price”字段的值正序排列:
GET /ecommerce/product/_search
{
"query" : {
"match" : {
"name" : "yagao"
}
},
"sort" : [
{
"price":"asc"
}
]
}
範圍查詢:
實例:
GET /ecommerce/product/_search
{
"query" : {"match_all" : {} },
"from" : 1,
"size" : 2
}
查詢指定字段:
GET /ecommerce/product/_search
{
"query": {"match_all" : {} },
"_source":["name","price"]
}
3.query filter
功能:實現數據過濾
查詢出價格高於25的數據:
GET /ecommerce/product/_search
{
"query" : {
"bool" : {
"must" : {
"match" : {
"name" : "yagao"
}
},
"filter": {
"range":{
"price" : {"gt":30}
}
}
}
}
}
4.full-text search
功能:實現全文檢索,即:只要“producer”字段中包含 yagao或producer都會被搜索出來,也就是說“部分匹配”的對象會被搜索到。
GET /ecommerce/product/_search
{
"query":{
"match" : {
"producer":"yagao producer"
}
}
}
結果說明:
max_score:本次查詢結果中最高的匹配度
hits.hits._score:具體數據的匹配度
5.phrase search
功能:短語匹配搜索,即:只有當對象的指定字段包含完整關鍵詞時,纔會被搜索出來。
跟全文檢索相反,全文檢索會將輸入的搜索穿拆散開,去倒排索引裏面去一一匹配,只要能夠匹配上任意一個拆解後的單詞,就可以作爲結果返回phrase search
要求輸入的搜索串,必須在指定的字段文本中,完全包含一模一樣的,纔可以算匹配,才能作爲結果返回。
GET /ecommerce/product/_search
{
"query":{
"match_phrase":{
"producer":"yagao producer"
}
}
}
6.highlight search
功能:搜索結果高亮顯示
GET /ecommerce/product/_search
{
"query":{
"match" : {
"producer":"producer"
}
},
"highlight":{
"fields" : {
"producer" : {}
}
}
}
看到你的輸出發現並沒有哪裏是高亮的對吧?難道是自己語句寫錯了?別擔心,如果你的輸出沒有報“error”,只是沒有高亮顯示,那麼你寫的沒錯,因爲這裏的高亮,指的是輸出的內容再html中是高亮顯示的,即只是將輸出結果中的關鍵詞放到了一個<em>關鍵詞</em>中。
輸出:
{ "took": 29, "timed_out": false, "_shards": { "total": 5, "successful": 5, "failed": 0 }, "hits": { "total": 4, "max_score": 0.25811607, "hits": [ { "_index": "ecommerce", "_type": "product", "_id": "1", "_score": 0.25811607, "_source": { "name": "good gaolujie yagao", "desc": "gaoxiao meibai", "price": 30, "producer": "gaolujie producer", "tags": [ "meibai", "fangzhu" ] }, "highlight": { "producer": [ "gaolujie <em>producer</em>" ] } }, { "_index": "ecommerce", "_type": "product", "_id": "3", "_score": 0.25811607, "_source": { "name": "zhonghua yagao", "desc": "caoben meibai", "price": 20, "producer": "gaolujie producer", "tags": [ "qingxin" ] }, "highlight": { "producer": [ "gaolujie <em>producer</em>" ] } }, { "_index": "ecommerce", "_type": "product", "_id": "2", "_score": 0.1805489, "_source": { "name": "jiajieshi yagao", "desc": "youxiao meibai", "price": 35, "producer": "gaolujie producer", "tags": [ "meibai", "fangzhu" ] }, "highlight": { "producer": [ "gaolujie <em>producer</em>" ] } }, { "_index": "ecommerce", "_type": "product", "_id": "4", "_score": 0.14638957, "_source": { "name": "heiren yagao", "desc": "heiren meibai", "price": 50, "producer": "heiren yagao producer", "tags": [ "meibai" ] }, "highlight": { "producer": [ "heiren yagao <em>producer</em>" ] } } ] } } |
7.倒排索引
倒排索引的意義在於“按詞找文”,它是全文搜索的基礎。
什麼是倒排索引:
爲了搞清什麼是倒排索引,我們分步推演。
首先什麼是索引?
我不能說索引是什麼,可是我可以說它像什麼。它就像是一本書的目錄。我們看着目錄就知道自己想看的內容在哪一頁了。所以,索引的目的是讓我們更快找到對象的工具。爲了實現這種功能,有很多經典的實現,比如B樹索引,唯一索引等等。就像一本書的目錄也需要印在紙上,因此一本添加了目錄的書會佔用更多的書頁。同理,在數據庫中,一個有索引的表會佔用更多的存儲空間。也就是拿空間換時間。消耗更多的空間資源,節約更多的搜索時間。
倒排索引:
A數據的words字段的值:hello today dog cat
B數據的words字段的值:boby free hello fish
C數據的words字段的值:shell today hello
D數據的words字段的值:hi fish
===>
words字段的值中的詞 |
在哪個數據出現過 |
hello |
A,B,C |
today |
A,C |
dog |
A |
cat |
A |
boby |
B |
free |
B |
fish |
B,D |
shell |
C |
hi |
D |
好理解嗎?
再直白一點,我來講個故事。
那是去年冬天的一個深夜,我們產品需要上線,於是我們就很自然的加了班。那天很冷,經理決定請大家吃夜宵,看了一下這麼晚只有燒烤了。於是我們決定叫點燒烤擼一擼,於是開始點菜。
小張說:我要茄子,土豆,平菇,大魷魚,羊肉,水餃
小李說:我要韭菜,年糕,羊肉,土豆,豬腰子,水餃
小王說:我要五花肉,大魷魚,年糕,羊肉,牛肉
經理說:好的,我要茄子,年糕,羊肉,餛飩。
於是經理整理一下大家的菜單,怕直接發過去,老闆給弄錯了。於是得到下面這份訂單:
菜品 |
點餐人 |
茄子 |
小張,經理 |
土豆 |
小張,小李 |
平菇 |
小張 |
大魷魚 |
小張,小王 |
羊肉 |
小張,小李,小王,經理 |
水餃 |
小張,小李 |
韭菜 |
小李 |
年糕 |
小李,小王,經理 |
豬腰子 |
小李 |
五花肉 |
小王 |
牛肉 |
小王 |
餛飩 |
經理 |
對,就是這樣,假裝我就是吃混沌那個!
簡單的說就是:
正排索引:按文找詞
倒排索引:按詞找文
小結:方法很多,根據場景適時用即可。