在前面幾節的内容中,我們學習索引、字段映射、分析器等,這些都是使用ES的基礎,就像在資料庫中建立表一樣,基礎工作做好以後,我們就要真正的使用它了,這一節我們要看看怎麼向索引裡寫入資料、修改資料、删除資料,至于搜尋嘛,因為ES的主要功能就是搜尋,是以搜尋的相關功能我們後面會展開講。
Document的建立與更新
索引中的資料叫做document,和資料中的一條記錄是一樣的,而索引就像資料庫中的一張表,我們向索引中添加資料,就像在資料庫表中添加一條記錄一樣。下面我們看看怎麼向索引中添加資料,
PUT /<index>/_doc/<_id>
POST /<index>/_doc/
PUT /<index>/_create/<_id>
POST /<index>/_create/<_id>
在這個POST請求中,
<index>
也就是索引的名字是必須的,這就好比我們向資料庫中插入記錄,要知道往哪張表裡插是一樣的。
<index>
後面可以是
_doc
或者
_create
,這兩個是什麼意思呢?咱們慢慢看,除了這兩個差別以外,再有就是請求的方法了,分為
POST
和
PUT
兩種。一般情況下,
POST
用于資料的插入,
PUT
使用者資料的修改,是不是這樣呢?咱們把這4種方式都試一下,首先我們看一下
POST /<index>/_doc/
這種方式的請求,
POST /ik_index/_doc
{
"id": 1,
"title": "蘋果",
"desc": "蘋果真好吃"
}
在這裡,索引我們使用的是上一節建立的
ik_index
,執行一下。然後我們再查詢一下這個索引,
GET /ik_index/_search
傳回結果如下:
{
"took": 1000,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "ik_index",
"_type": "_doc",
"_id": "1",
"_score": 1,
"_source": {
"id": 1,
"title": "大興龐各莊的西瓜",
"desc": "大興龐各莊的西瓜真是好吃,脆沙瓤,甜掉牙"
}
},
{
"_index": "ik_index",
"_type": "_doc",
"_id": "fEsN-HEBZl0Dh1ayKWZb",
"_score": 1,
"_source": {
"id": 1,
"title": "蘋果",
"desc": "蘋果真好吃"
}
}
]
}
}
我們重點看一下
hits
,這是我們查詢出的結果,第一條是我們上一節存入的資料,不用管它。我們看一下第二條記錄,注意一下
_id
這個字段,這個
_id
是這條記錄在索引裡的唯一辨別,在插入資料的請求中,我們沒有指定這個id,ES給我們自動生成了
fEsN-HEBZl0Dh1ayKWZb
。那麼我們可不可以指定呢?試一下,
POST /ik_index/_doc/2
{
"id": 1,
"title": "香蕉",
"desc": "香蕉真好吃"
}
注意我們發送的請求,
_doc
後面加了
2
,這樣就指定了id,執行一下。然後再次查詢,傳回的結果中,我們隻截取
hits
的部分,如下:
"hits": [
{
"_index": "ik_index",
"_type": "_doc",
"_id": "1",
"_score": 1,
"_source": {
"id": 1,
"title": "大興龐各莊的西瓜",
"desc": "大興龐各莊的西瓜真是好吃,脆沙瓤,甜掉牙"
}
},
{
"_index": "ik_index",
"_type": "_doc",
"_id": "fEsN-HEBZl0Dh1ayKWZb",
"_score": 1,
"_source": {
"id": 1,
"title": "蘋果",
"desc": "蘋果真好吃"
}
},
{
"_index": "ik_index",
"_type": "_doc",
"_id": "2",
"_score": 1,
"_source": {
"id": 1,
"title": "香蕉",
"desc": "香蕉真好吃"
}
}
]
我們看到插入的
香蕉
記錄,它的
_id
是
2
。那麼
POST
請求中指定的id在索引中存在,會是什麼情況呢?我們再看一下,
POST /ik_index/_doc/1
{
"id": 1,
"title": "香蕉",
"desc": "香蕉真好吃"
}
還是
香蕉
這條資料,我們指定id=1,id=1這條資料在索引中是存在的,我們執行一下,然後查詢,傳回的結果如下:
"hits": [
{
"_index": "ik_index",
"_type": "_doc",
"_id": "fEsN-HEBZl0Dh1ayKWZb",
"_score": 1,
"_source": {
"id": 1,
"title": "蘋果",
"desc": "蘋果真好吃"
}
},
{
"_index": "ik_index",
"_type": "_doc",
"_id": "2",
"_score": 1,
"_source": {
"id": 1,
"title": "香蕉",
"desc": "香蕉真好吃"
}
},
{
"_index": "ik_index",
"_type": "_doc",
"_id": "1",
"_score": 1,
"_source": {
"id": 1,
"title": "香蕉",
"desc": "香蕉真好吃"
}
}
]
我們看到之前的那條資料被修改了,是以,關于
POST /<index>/_doc/<_id>
,這種添加資料的方式,我們得出結論如下:
- <_id>不指定時,ES會為我們自動生成id;
- 指定<_id>時,且id在索引中不存在,ES将添加一條指定id的資料;
- 指定<_id>時,但id在索引中存在,ES将會更新這條資料;
接下來我們再看看
_doc
方式的
PUT
請求方式,我們先不指定id,看看會是什麼情況,請求如下:
PUT /ik_index/_doc
{
"id": 1,
"title": "葡萄",
"desc": "葡萄真好吃"
}
執行一下,傳回如下結果:
{
"error": "Incorrect HTTP method for uri [/ik_index/_doc] and method [PUT], allowed: [POST]",
"status": 405
}
錯誤資訊說我們的請求不對,讓我們使用
POST
請求,看來
PUT
請求不指定id是不行的。我們再看看指定一個不存在的id,是什麼情況,如下:
PUT /ik_index/_doc/3
{
"id": 1,
"title": "葡萄",
"desc": "葡萄真好吃"
}
執行成功,再查詢一下,
"hits": [
……
{
"_index": "ik_index",
"_type": "_doc",
"_id": "3",
"_score": 1,
"_source": {
"id": 1,
"title": "葡萄",
"desc": "葡萄真好吃"
}
}
]
資料添加成功。再看看指定一個存在的id是什麼情況,那當然是修改了,我們再試一下,
PUT /ik_index/_doc/3
{
"id": 1,
"title": "橘子",
"desc": "橘子真好吃"
}
"hits": [
……
{
"_index": "ik_index",
"_type": "_doc",
"_id": "3",
"_score": 1,
"_source": {
"id": 1,
"title": "橘子",
"desc": "橘子真好吃"
}
}
]
沒有問題,修改成功。
POST /<index>/_doc/<_id>
這種方式的總結如下:
-
必須指定,不指定會報錯;<_id>
-
在索引中不存在,為添加新資料;<_id>
-
在索引中存在,為修改資料;<_id>
_doc
這種請求的
POST
PUT
都嘗試過了,再看看
_create
這種請求,先看看不指定id是什麼情況,如下:
POST /ik_index/_create
{
"id": 1,
"title": "桃子",
"desc": "桃子真好吃"
}
傳回錯誤資訊如下:
{
"error": {
"root_cause": [
{
"type": "invalid_type_name_exception",
"reason": "mapping type name [_create] can't start with '_' unless it is called [_doc]"
}
],
"type": "invalid_type_name_exception",
"reason": "mapping type name [_create] can't start with '_' unless it is called [_doc]"
},
"status": 400
}
具體内容我們也不去解讀了,總之是不可以,然後加個索引中不存在id試一下,
POST /ik_index/_create/4
{
"id": 1,
"title": "桃子",
"desc": "桃子真好吃"
}
傳回結果建立成功,查詢如下:
"hits": [
……
{
"_index": "ik_index",
"_type": "_doc",
"_id": "4",
"_score": 1,
"_source": {
"id": 1,
"title": "桃子",
"desc": "桃子真好吃"
}
}
]
如果id在索引中存在呢?再試,
POST /ik_index/_create/3
{
"id": 1,
"title": "桃子",
"desc": "桃子真好吃"
}
傳回錯誤:
{
"error": {
"root_cause": [
{
"type": "version_conflict_engine_exception",
"reason": "[3]: version conflict, document already exists (current version [2])",
"index_uuid": "W2X_riHIT4u678p8HZwnEg",
"shard": "0",
"index": "ik_index"
}
],
"type": "version_conflict_engine_exception",
"reason": "[3]: version conflict, document already exists (current version [2])",
"index_uuid": "W2X_riHIT4u678p8HZwnEg",
"shard": "0",
"index": "ik_index"
},
"status": 409
}
大緻的意思是,資料已經存在了,不能再添加新記錄,看來
_create
這種方式還是比較嚴格的,總結如下:
- id必須指定;
- 指定的id如果在索引中存在,報錯,添加不成功;
- 指定的id在索引中不存在,添加成功,符合預期;
再看看
_create
的
PUT
,應該和
POST
正好相反吧?我們試一下,先不指定id,試一下,
PUT /ik_index/_create
{
"id": 1,
"title": "火龍果",
"desc": "火龍果真好吃"
}
傳回錯誤,不指定id肯定是不行的,錯誤資訊就不給大家貼出來了,然後再指定一個不存在的id,
PUT /ik_index/_create/5
{
"id": 1,
"title": "火龍果",
"desc": "火龍果真好吃"
}
建立成功,查詢結果就不給大家展示了,然後再換一個存在的id,如下:
PUT /ik_index/_create/4
{
"id": 1,
"title": "火龍果",
"desc": "火龍果真好吃"
}
傳回了錯誤的資訊,如下,和
POST
請求是一樣的,
{
"error": {
"root_cause": [
{
"type": "version_conflict_engine_exception",
"reason": "[4]: version conflict, document already exists (current version [1])",
"index_uuid": "W2X_riHIT4u678p8HZwnEg",
"shard": "0",
"index": "ik_index"
}
],
"type": "version_conflict_engine_exception",
"reason": "[4]: version conflict, document already exists (current version [1])",
"index_uuid": "W2X_riHIT4u678p8HZwnEg",
"shard": "0",
"index": "ik_index"
},
"status": 409
}
我們得出如下的結論:
-
這種形式的_create
POST
是一樣的,沒有差別;PUT
- id必須在索引中不存在;
Document的删除
有了添加,肯定會有删除,删除的方式很簡單,請求格式如下:
DELETE /<index>/_doc/<_id>
發送
delete
請求,指定資料的id,就可以了,我們試一下,删除剛剛添加的
火龍果
資料,它的id是
5
,我們發送請求如下:
DELETE /ik_index/_doc/5
執行成功,資料被成功的删除。
根據id查詢Document
根據id查詢資料也很簡單,發送如下請求就可以完成查詢,
GET <index>/_doc/<_id>
我們需要指定索引的名稱,以及要查詢資料的id,如下:
GET ik_index/_doc/3
{
"_index": "ik_index",
"_type": "_doc",
"_id": "3",
"_version": 2,
"_seq_no": 5,
"_primary_term": 3,
"found": true,
"_source": {
"id": 1,
"title": "橘子",
"desc": "橘子真好吃"
}
}
根據id成功的查詢出來結果。
好了~ 到這裡,ES資料的增删改都介紹了,下節開始,我們看看ES的核心功能——搜尋。