ES[7.6.x]學習筆記(八)數據的增刪改

在前面幾節的內容中,我們學習索引、字段映射、分析器等,這些都是使用ES的基礎,就像在數據庫中創建表一樣,基礎工作做好以後,我們就要真正的使用它了,這一節我們要看看怎麼向索引裏寫入數據、修改數據、刪除數據,至於搜索嘛,因爲ES的主要功能就是搜索,所以搜索的相關功能我們後面會展開講。

Document的創建與更新

索引中的數據叫做document,和數據中的一條記錄是一樣的,而索引就像數據庫中的一張表,我們向索引中添加數據,就像在數據庫表中添加一條記錄一樣。下面我們看看怎麼向索引中添加數據,

PUT /<index>/_doc/<_id>

POST /<index>/_doc/

PUT /<index>/_create/<_id>

POST /<index>/_create/<_id>

在這個POST請求中,<index>也就是索引的名字是必須的,這就好比我們向數據庫中插入記錄,要知道往哪張表裏插是一樣的。<index>後面可以是_doc或者_create,這兩個是什麼意思呢?咱們慢慢看,除了這兩個區別以外,再有就是請求的方法了,分爲POSTPUT兩種。一般情況下,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": "香蕉真好吃"
                }
            }
        ]

我們看到插入的香蕉記錄,它的_id2。那麼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這種請求的POSTPUT都嘗試過了,再看看_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在索引中不存在,添加成功,符合預期;

再看看_createPUT,應該和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這種形式的POSTPUT是一樣的,沒有區別;
  • id必須指定;
  • 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的核心功能——搜索。

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