91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

ElasticSearch常用操作:文檔篇

發布時間:2020-07-30 11:17:27 來源:網絡 閱讀:2216 作者:xpleaf 欄目:大數據

[TOC]


1 新建文檔

1.1 指定id

PUT my_blog/article/1
{
  "id":1,
  "title":"elasticsearch",
  "posttime":"2017-05-01",
  "content":"elasticsearch is helpfull!"
}

返回:

{
  "_index": "my_blog",
  "_type": "article",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": true
}

版本號會隨著文檔的更新自動遞增。

1.2 不指定id

不指定id,es會自動生成,但是這時只能使用post:

POST my_blog/article
{
  "id":2,
  "title":"spark",
  "posttime":"2017-05-01",
  "content":"spark is helpfull!"
}

返回:

{
  "_index": "my_blog",
  "_type": "article",
  "_id": "AWagTCv8O1qbT1zqbREV",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "created": true
}

2 獲取文檔

2.1 普通獲取

獲取存在的文檔:

GET my_blog/article/1

返回:

{
  "_index": "my_blog",
  "_type": "article",
  "_id": "1",
  "_version": 1,
  "found": true,
  "_source": {
    "id": 1,
    "title": "elasticsearch",
    "posttime": "2017-05-01",
    "content": "elasticsearch is helpfull!"
  }
}

獲取不存在的文檔:

GET my_blog/article/2

返回:

{
  "_index": "my_blog",
  "_type": "article",
  "_id": "2",
  "found": false
}

2.2 測試文檔是否存在

使用HEAD可以測試文檔是否存在:

HEAD my_blog/article/1
200 - OK

HEAD my_blog/article/2
404 - Not Found

2.3 批量獲取

不同index不同type:

GET _mget
{
  "docs":[
    {
      "_index":"my_blog",
      "_type":"article",
      "_id":1
    },
    {
      "_index":"twitter",
      "_type":"tweet",
      "_id":2
    }
  ]
}

同一index下不同type:

GET my_blog/_mget
{
  "docs":[
    {
      "_type":"article",
      "_id":1
    },
    {
      "_type":"essay",
      "_id":2
    }
  ]
}

同一index同一type:

GET my_blog/article/_mget
{
  "docs":[
    {"_id":1},
    {"_id":2}
  ]
}

或:

GET my_blog/article/_mget
{
  "ids":[1,2]
}

3 更新文檔

es更新文檔的原理為:先找到這個文檔,刪除舊的文檔內容執行更新,更新完后再索引最新的文檔。

先添加下面一份文檔:

PUT test/type1/1
{
  "counter":1,
  "tags":["red"]
}

3.1 更新文檔字段內容

給counter的值增加4:

POST test/type1/1/_update
{
  "script": {
    "inline": "ctx._source.counter += params.count",
    "lang": "painless",
    "params": {
      "count":4
    }
  }
}

Note1:命令中inline是執行的腳本,ctx是腳本語言中的一個執行對象,painless是es內置的一種腳本語言,params是參數集合;

Note2:ctx對象除了可以訪問_source之外,還可以訪問_index_type_id_version_routing_parent等字段;

對tags字段增加一個值:

POST test/type1/1/_update
{
  "script":{
    "inline":"ctx._source.tags.add(params.tag)",
    "lang":"painless",
    "params":{
      "tag":"blue"
    }
  }
}

3.2 新增與移除字段

給test/type1/1添加一個字段name:

POST test/type1/1/_update
{
  "script": {
    "inline": "ctx._source.name=\"test\""
  }
}

上面的命令也可以簡寫為:{"script":""ctx._source.name=\"test\""}

移除name字段:

POST test/type1/1/_update
{
  "script": {
    "inline": "ctx._source.remove(\"name\")"
  }
}

3.3 upsert操作

如果文檔不存在,upsert會新建一個文檔,文檔存在,則正常執行script腳本。如下:

POST test/type1/2/_update
{
  "script": {
    "inline": "ctx._source.counter += params.count",
    "lang": "painless",
    "params": {
      "count":4
    }
  },
  "upsert": {
    "counter":1,
    "tag":["pink"]
  }
}

如果test/type1/2存在,則更新count,如果不存在,則新建一個包含字段counter和tag的文檔。

返回:

{
  "_index": "test",
  "_type": "type1",
  "_id": "2",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  }
}

3.4 基于doc的更新方式

也可以使用doc的方式來更新字段內容或者添加新的字段:

POST myblog/article/1/_update
{
  "doc": {
    "title":"test new title"
  }
}

POST myblog/article/1/_update
{
  "doc": {
    "new field":"this is a new field"
  }
}

4 查詢更新

POST my_blog/_update_by_query
{
  "script":{
    "inline": "ctx._source.content = params.content",
    "lang": "painless",
    "params": {
      "content":"spark is popular"
    }
  },
  "query":{
    "term": {
      "title": {
        "value": "spark"
      }
    }
  }
}

返回:

{
  "took": 33,
  "timed_out": false,
  "total": 1,
  "updated": 1,
  "deleted": 0,
  "batches": 1,
  "version_conflicts": 0,
  "noops": 0,
  "retries": {
    "bulk": 0,
    "search": 0
  },
  "throttled_millis": 0,
  "requests_per_second": -1,
  "throttled_until_millis": 0,
  "failures": []
}

5 刪除文檔

DELETE my_blog/article/2

如果在索引文檔時指定了路由,刪除時也可以增加路由參數:

DELETE my_blog/article/2?routing=user123

Note1:如果刪除時路由值不正確,刪除會失敗;

Note2:當映射的_routing被設定為required且沒有指定的路由值時,執行刪除操作將拋出路由缺失異常并拒絕該請求;

6 查詢刪除

POST my_blog/_delete_by_query
{
  "query":{
    "term": {
      "title": {
        "value": "mybatis"
      }
    }
  }
}

刪除一個type下的所有文檔:

POST my_blog/article/_delete_by_query
{
  "query":{
    "match_all":{}
  }
}

7 批量操作

7.1 命令格式

使用如下命令:

curl -XPOST 'localhost:9200/indexname/_bulk?prettry' --data-binary @accounts.json

accounts.json文件應該滿足下面的格式:

action_and_meta_data行
data行

Note1:action_and_meta_data行中,action必須是index、create、update或者delete,metadata需要指明需要被操作文檔的_index_type以及_id

Note2:data行就是添加的數據,添加文檔時就需要data行;

Note3:每一行的結尾處都必須有換行符"\n",最后一行也要有,換行符可以有效地分隔每行;

7.2 添加文檔

{"index": {"_index": "my_blog"}, "_type": "article", "_id": "1"}
{"title": "blog title"}

{"create": {"_index": "my_blog", "_type": "article", "_id": "1"}}
{"title": "blog title"}

不寫id也是可以的。

7.3 刪除文檔

{"delete": {"_index": "website", "_type": "blog", "_id": "123"}}

7.4 綜合案例

下面內容包含索引文檔請求、更新文檔請求和刪除文檔請求:

{"delete": {"_index": "website", "_type": "blog", "_id": "123"}}

{"create": {"_index": "website", "_type": "blog", "_id": "123"}}
{"title": "blog title"}

{"index": {"_index": "website", "_type": "blog"}}
{"title": "blog title"}

{"update": {"_index": "website", "_type": "blog", "_id": "123"}}
{"doc": {"title": "blog title"}}

8 版本控制

初次接觸,8.2可以忽略,了解一下8.3的命令操作即可。

es進行文檔更新時,首先讀取源文檔,對原文檔進行更新操作,更新操作執行完成以后再重新索引整個文檔。

8.1 鎖控制

很有可能多個用戶同時對同一份文檔數據進行修改更新操作,這時就需要進行事務性控制,或者說需要進行并發控制。

8.1.1 悲觀鎖控制

如果有線程對數據進行修改就對數據進行鎖定,其他線程想要訪問需要等待當前鎖定釋放,這樣可確保同一時刻最多只有一個線程訪問數據。傳統的關系型數據庫就用到了很多這種鎖機制,比如行鎖、表鎖、讀鎖、寫鎖等。

8.1.2 樂觀鎖控制

對數據資源不會鎖定,只有在數據提交操作時檢查是否違反數據完整性。Elasticsearch使用的就是樂觀鎖機制,樂觀鎖適用于讀操作比寫操作比較多的應用類型,可省去鎖開銷,提高吞吐量。

8.2 es的版本控制

既然es使用的是樂觀鎖,那么如何保證舊的數據不會覆蓋新的數據呢?在es中使用_version來進行版本的控制,文檔每被更新一次,其就會加1.

es的文檔版本控制機制主要有內部版本控制和外部版本控制:

  • 內部版本控制機制要求每次操作請求,只有當版本號相等時才能操作成功;
  • 外部版本控制要求外部文檔版本比內部文檔版本高時才能更新成功;

其實不管是請求獲取數據還是請求更新數據,都是可以攜帶版本號的,不管情況多復雜,只需要記住下面兩點即可:

  • 1.如果只是請求獲取數據操作,內部版本控制機制生效,外部版本控制機制不生效,情況如下:
    • a.不攜帶版本號,操作成功:
    • b.攜帶內部版本號,那么一定要跟文檔當前的版本號相等;
    • c.攜帶外部版本號,那么一定要跟文檔當前的版本號相等;
  • 2.如果是更新操作,情況如下:
    • a.不攜帶版本號,操作成功,文檔版本號會加1;
    • b.攜帶內部版本號,那么一定要跟文檔當前的版本號相等,文檔版本號會加1;
    • c.攜帶外部版本號,那么一定要大于文檔當前的版本號,文檔版本會等于攜帶的版本號;

也可以從是否攜帶版本號的角度去思考這個問題:

  • 1.不攜帶版本號,請求獲取數據和更新操作都會成功;
  • 2.攜帶內部版本號,不管哪種操作,要求一定要與文檔版本號相等;
  • 3.攜帶外部版本號,請求獲取數據時版本號需要相等,更新操作時版本號需要大于文檔版本號;

至于es為什么這樣設計?其實內部版本號是es提供的,但實際上你可能也有自己業務或程序上的需求,就是說你的應用系統本身就維護了一個版本號,或者說你自己想通過某種機制去維護一個版本號,那么就可以使用外部版本號。

8.3 命令操作

GET website/blog/1?version=1

PUT website/blog/1?version=5&version_type=external

9 路由機制

9.1 分片位置計算與案例

當索引有多個分片時,索引一個文檔,es是如何確定將文檔保存到哪一個文檔上的呢?假設環境如下:

Master Node:
shard0(primary)
shard1 
shard2(primary)

Common Node:
shard0
shard1(primary)
shard2

es的路由機制通過哈希算法,將具有相同哈希值的文檔放置到同一個主分片中,方法如下:

shard = hash(routing) % number_of_primary_shards

假如我們添加一份文檔,沒有指定id,es給我們生成的id是AWagTCv8O1qbT1zqbREV,套用上面的公式,shard就應該為:

shard = hash("AWagTCv8O1qbT1zqbREV") % 3

當然哈希函數的實現不一定,我們可以在python中調用一下其提供的hash()函數來演示一下上面的計算:

>>> shard = hash("AWagTCv8O1qbT1zqbREV") % 3
>>> shard
2

顯然,該文檔會被存儲到分片2也就是第3個分片上。

通過上面的介紹可以知道,默認的路由模式可以保證數據平均分布,不過也可以自定義routing值,從而指定文檔的存儲位置。

9.2 es查詢流程與自定義routing值

假如存在一個有50個分片的索引,在集群上執行一次查詢的過程如下:

  • (1)查詢請求首先被集群中的一個節點接收;
  • (2)接收到這個請求的節點,將這個查詢廣播到這個索引的每個分片上;
  • (3)每個分片執行完搜索查詢并返回結果;
  • (4)結果在通道節點上合并、排序并返回給用戶;

可以自定義路由值來避免這種廣播,下面舉一個案例進行說明。

正常我們這樣來添加一份文檔:

PUT website/article/1
{
    "title":"My first blog entry",
    "text":"Just trying this out...",
    "user":"user123"
}

查詢時,希望查詢user123的所有文章:

GET website/article/_search
{
    "query":{
        "term":{"user":"user123"}
    }
}

顯然這樣查詢,會按照上面的流程去走,也就是請求會被發送到所有的分片上,這時希望優化一下。

將user作為routing來添加文檔:

PUT website/article/1?routing=user123
{
    "title":"My first blog entry",
    "text":"Just trying this out...",
    "user":"user123"
}

指定routing值后,后面user123發表的文章(文檔)都會被存儲到同一個分片上,這里假設是分片1,這樣一來,我們再查詢user123發表的文章時,只需要在search時指定routing值,那么就不會被廣播請求的情況了,請求直接到達分片1,查詢如下:

GET website/article/_search?routing=user123

Note1:這樣也會帶來問題,比如user123發表了數十萬篇文章,但是其它用戶只有很少的文章,顯然數據的分配就不均衡了;

Note2:也可以為文檔指定多個路由值,路由值之間使用逗號分隔(這樣一來,文檔就有可能會被分配到多個分片上,至于滿足其條件的這幾個分片,es是如何選擇的,通過什么算法,可以自行研究一下);

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

扶余县| 乃东县| 泽库县| 饶平县| 武安市| 镇康县| 宁国市| 应用必备| 武威市| 平乐县| 闽侯县| 姜堰市| 磴口县| 那曲县| 花莲市| 南京市| 灵山县| 汕头市| 遵义市| 灵武市| 阿克| 景宁| 米泉市| 杂多县| 安康市| 赤水市| 濮阳市| 安庆市| 元江| 青浦区| 宕昌县| 灵璧县| 太原市| 商城县| 兴安县| 正蓝旗| 宣化县| 泽州县| 邮箱| 恩平市| 临沂市|