白话Elasticsearch01- 结构化搜索之使用term query来搜索数据
文章目錄
- 需求描述
- ES版本
- _bulk 批量寫幾條數據
- _bulk 用法
- 返回結果分析
- 字段Dynamic Mapping
- Dynamic Mapping 中 text類型的字段
- 查看分詞
- field
- field.keyword
- 幾個小例子
- 根據用戶ID搜索帖子
- 搜索沒有隱藏的帖子
- 根據發帖日期搜索帖子
- 根據帖子ID搜索帖子
- 刪除索引,指定articleID的類型
需求描述
這個系列我們來跟著中華石杉老師來系統的學習下ES
課程地址: https://www.roncoo.com/view/55
需求背景: 一個普通的論壇,根據用戶ID、是否隱藏、帖子ID、發帖日期來搜索帖子
ES版本
我這里用的版本是ES6.4.1 , 只要是5.X以上的版本都使用。目前ES的版本已經到了7.0.
Kibana用的也是對應的kibana-6.4.1-windows-x86_64
Term Filter 不推薦使用了,推薦使用 Term Query
https://www.elastic.co/guide/en/elasticsearch/reference/6.4/query-dsl-term-filter.html#query-dsl-term-filter
6.4版本的 Term Query說明
https://www.elastic.co/guide/en/elasticsearch/reference/6.4/query-dsl-term-query.html
_bulk 批量寫幾條數據
POST /forum/article/_bulk { "index": { "_id": 1 }} { "articleID" : "XHDK-A-1293-#fJ3", "userID" : 1, "hidden": false, "postDate": "2017-01-01" } { "index": { "_id": 2 }} { "articleID" : "KDKE-B-9947-#kL5", "userID" : 1, "hidden": false, "postDate": "2017-01-02" } { "index": { "_id": 3 }} { "articleID" : "JODL-X-1937-#pV7", "userID" : 2, "hidden": false, "postDate": "2017-01-01" } { "index": { "_id": 4 }} { "articleID" : "QQPX-R-3956-#aD8", "userID" : 2, "hidden": true, "postDate": "2017-01-02" }_bulk 用法
BULK API官網說明: https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-bulk.html
簡單說下_bulk api , 批量執行,對執行的json串有嚴格的格式要求,不要格式化JSON串
返回結果分析
直接在kibana的DevTool中執行上述JSON即可
返回結果
#! Deprecation: the default number of shards will change from [5] to [1] in 7.0.0; if you wish to continue using the default of [5] shards, you must manage this on the create index request or with an index template {"took": 1581,"errors": false,"items": [{"index": {"_index": "forum","_type": "article","_id": "1","_version": 1,"result": "created","_shards": {"total": 2,"successful": 1,"failed": 0},"_seq_no": 0,"_primary_term": 1,"status": 201}}......篇幅原因,省略其他三個的顯示}] }結果說明:
- took: query的時間,不包括fetch
再看下_shard節點下的total和successful信息
- total: 2 一共兩個shard需要執行 ,一個primary shard ,一個
replicas shard . 因為我們在同一個機器上起的(默認使用的 主shard 5 副本shard 1的配置)。 主shard 和 副本shard不能在同一個node上,所以該副本shard并未分配,所以這里successful 為1 。
通過head插件我們也可以窺之一二
字段Dynamic Mapping
- POST /forum/article/_bulk es會自動創建名為forum的index和名為article的 type
- 未提前設置field類型的話,es會通過Dynamic Mapping的方式來自動映射字段類型 ,我們來看下 GET /forum/_mapping/article
Dynamic Mapping 中 text類型的字段
我們重點來看下 articleID
- es 5.x版本中對于type=text,默認會設置兩個field, 一個是field本身,比如articleID,就是分詞的, 另外一個,就是field.keyword,在這里就是用的話articleID.keyword,默認不分詞,最多保留256個字符("ignore_above": 256)
articleID.keyword,是es新版本內置建立的field,就是不分詞的。所以一個articleID過來的時候,會建立兩次索引,一次是自己本身,是要分詞的,分詞后放入倒排索引;
另外一次是基于articleID.keyword,不分詞,保留256個字符最多,直接一個字符串放入倒排索引中。
所以term filter,對text過濾,可以考慮使用內置的field.keyword來進行匹配。但是有個問題,默認就保留256個字符。所以盡可能還是自己去手動建立索引,指定not_analyzed吧。在新版本的es中,不需要指定not_analyzed也可以,將type=keyword即可。
"articleID": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},查看分詞
查看下Dynamic mapping下,text類型的分詞
field
GET /forum/_analyze {"field": "articleID","text": "XHDK-A-1293-#fJ3" }可以看到 articleID建立索引的時候,XHDK-A-1293-#fJ3被分詞成了 xhdk,a,1293,fj3
默認是analyzed的text類型的field,建立倒排索引的時候,就會對所有的articleID分詞,分詞以后,原本的articleID就沒有了,只有分詞后的各個word存在于倒排索引中。所以根據XHDK-A-1293-#fJ3 去查詢,肯定是在 xhdk,a,1293,fj3 中查找不到數據的。
field.keyword
GET /forum/_analyze {"field": "articleID.keyword","text": "XHDK-A-1293-#fJ3" }term,是不對搜索文本分詞的,直接將輸入的內容去倒排索引中匹配,XHDK-A-1293-#fJ3 --> XHDK-A-1293-#fJ3;但是articleID建立索引的時候,XHDK-A-1293-#fJ3 --> xhdk,a,1293,fj3 ,所以使用 articleID是查不到的, articleID.keyword 是可以查到的。 如下所示
幾個小例子
term filter/query:對搜索文本不分詞,直接拿去倒排索引中匹配,你輸入的是什么,就去匹配什么。 比如說,如果對搜索文本進行分詞的話,“helle world” --> “hello”和“world”,兩個詞分別去倒排索引中匹配 。 term,“hello world” --> “hello world”,直接去倒排索引中匹配“hello world”
這里我們不關心相關度即_score,僅僅是希望通過filter過濾出來數據,所以 使用了 constant_score , 設置相關度都是1.
先通過head插件看下數據
根據用戶ID搜索帖子
GET /forum/article/_search {"query": {"constant_score": {"filter": {"term": {"userID": 1}}}} }Term Query的寫法(推薦)
GET /forum/article/_search {"query": {"term": {"userID": "1"}} }搜索沒有隱藏的帖子
GET /forum/article/_search {"query": {"constant_score": {"filter": {"term": {"hidden": false}}}} }Term Query的寫法(推薦)
{"query": {"term": {"hidden": false}} }根據發帖日期搜索帖子
GET /forum/article/_search {"query": {"constant_score": {"filter": {"term": {"postDate": "2017-01-02"}}}} }Term Query的寫法(推薦)
GET /forum/article/_search {"query": {"term": {"postDate": "2017-01-02"}} }根據帖子ID搜索帖子
GET /forum/article/_search {"query": {"constant_score": {"filter": {"term": {"articleID": "QQPX-R-3956-#aD8"}}}} }Term Query的寫法(推薦)
GET /forum/article/_search {"query": {"term": {"articleID": "QQPX-R-3956-#aD8"}} }刪除索引,指定articleID的類型
這種Dynamic mapping的情況,肯定是查找不到數據了,要么指定 articleID.keyword。 更推薦自己設置類型,設置成 not_analyzed,或者直接將articleID設置為keyword更加方便。
那我們按照自己設置字段類型keyword的方式來演示下吧
先刪掉原來的forum索引
DELETE /forum手動設置 articleID的類型為 keyword
PUT /forum {"mappings":{"article":{"properties":{"articleID":{"type":"keyword"}}}} }這樣的話,就建好了一個 只有一個字段的type. 字段類型確定后無法修改,因為涉及到底層lucene的全文檢索。 但是可以增加字段,通過如下的方式,_bulk寫入數據的時候,新增幾個字段,因為沒有指定字段類型,所以是Dynamic Mapping的方式創建的
POST /forum/article/_bulk { "index": { "_id": 1 }} { "articleID" : "XHDK-A-1293-#fJ3", "userID" : 1, "hidden": false, "postDate": "2017-01-01" } { "index": { "_id": 2 }} { "articleID" : "KDKE-B-9947-#kL5", "userID" : 1, "hidden": false, "postDate": "2017-01-02" } { "index": { "_id": 3 }} { "articleID" : "JODL-X-1937-#pV7", "userID" : 2, "hidden": false, "postDate": "2017-01-01" } { "index": { "_id": 4 }} { "articleID" : "QQPX-R-3956-#aD8", "userID" : 2, "hidden": true, "postDate": "2017-01-02" }看下 field的類型
GET /forum/_mapping/article
再次查詢下 ,指定articleID的類型為keyword,查詢到了數據。
總結一下 term
(1)term filter:根據exact value進行搜索,數字、boolean、date天然支持
(2)text類型的字段需要建索引時指定為not_analyzed或者設置為keyword,才能用term query
(3)term 相當于SQL中的單個where條件
總結
以上是生活随笔為你收集整理的白话Elasticsearch01- 结构化搜索之使用term query来搜索数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Elasticsearch-06 Spr
- 下一篇: 白话Elasticsearch02- 结