ElasticSearch基本操作--Python篇

Elasticsearch 實際上提供了一系列 Restful API 來進行存取和查詢操作,我們可以使用 curl 等命令來進行操作尝抖,但畢竟命令行模式?jīng)]那么方便,所以這里我們就直接介紹利用 Python 來對接 Elasticsearch 的相關(guān)方法迅皇。

Python 中對接 Elasticsearch 使用的就是一個同名的庫昧辽,安裝方式非常簡單:

pip install elasticsearch

本文只做簡單的介紹,更多信息請查閱官方文檔登颓。

創(chuàng)建 Index
我們先來看下怎樣創(chuàng)建一個索引(Index)搅荞,這里我們創(chuàng)建一個名為 news 的索引:

from elasticsearch import Elasticsearch
 
es = Elasticsearch()
result = es.indices.create(index='news', ignore=400)
print(result)

如果創(chuàng)建成功,會返回如下結(jié)果:

{'acknowledged': True, 'shards_acknowledged': True, 'index': 'news'}

但這時如果我們再把代碼執(zhí)行一次的話,就會返回如下結(jié)果:

{'error': {'root_cause': [{'type': 'resource_already_exists_exception', 'reason': 'index [news/QM6yz2W8QE-bflKhc5oThw] already exists', 'index_uuid': 'QM6yz2W8QE-bflKhc5oThw', 'index': 'news'}], 'type': 'resource_already_exists_exception', 'reason': 'index [news/QM6yz2W8QE-bflKhc5oThw] already exists', 'index_uuid': 'QM6yz2W8QE-bflKhc5oThw', 'index': 'news'}, 'status': 400}

它提示創(chuàng)建失敗咕痛,status 狀態(tài)碼是 400痢甘,錯誤原因是 Index 已經(jīng)存在了。

注意這里我們的代碼里面使用了 ignore 參數(shù)為 400暇检,這說明如果返回結(jié)果是 400 的話产阱,就忽略這個錯誤不會報錯,程序不會執(zhí)行拋出異常块仆。

假如我們不加 ignore 這個參數(shù)的話:

es = Elasticsearch()
result = es.indices.create(index='news')
print(result)

再次執(zhí)行就會報錯了:

raise HTTP_EXCEPTIONS.get(status_code, TransportError)(status_code, error_message, additional_info)
elasticsearch.exceptions.RequestError: TransportError(400, 'resource_already_exists_exception', 'index [news/QM6yz2W8QE-bflKhc5oThw] already exists')

這樣程序的執(zhí)行就會出現(xiàn)問題构蹬,所以說,我們需要善用 ignore 參數(shù)悔据,把一些意外情況排除庄敛,這樣可以保證程序的正常執(zhí)行而不會中斷。

刪除 Index
刪除 Index 也是類似的科汗,代碼如下:

from elasticsearch import Elasticsearch
 
es = Elasticsearch()
result = es.indices.delete(index='news', ignore=[400, 404])
print(result)

這里也是使用了 ignore 參數(shù)藻烤,來忽略 Index 不存在而刪除失敗導(dǎo)致程序中斷的問題。

如果刪除成功头滔,會輸出如下結(jié)果:

{'acknowledged': True}

如果 Index 已經(jīng)被刪除怖亭,再執(zhí)行刪除則會輸出如下結(jié)果:

{'error': {'root_cause': [{'type': 'index_not_found_exception', 'reason': 'no such index', 'resource.type': 'index_or_alias', 'resource.id': 'news', 'index_uuid': '_na_', 'index': 'news'}], 'type': 'index_not_found_exception', 'reason': 'no such index', 'resource.type': 'index_or_alias', 'resource.id': 'news', 'index_uuid': '_na_', 'index': 'news'}, 'status': 404}

這個結(jié)果表明當前 Index 不存在,刪除失敗坤检,返回的結(jié)果同樣是 JSON兴猩,狀態(tài)碼是 400,但是由于我們添加了 ignore 參數(shù)早歇,忽略了 400 狀態(tài)碼倾芝,因此程序正常執(zhí)行輸出 JSON 結(jié)果,而不是拋出異常箭跳。

插入數(shù)據(jù)
Elasticsearch 就像 MongoDB 一樣晨另,在插入數(shù)據(jù)的時候可以直接插入結(jié)構(gòu)化字典數(shù)據(jù),插入數(shù)據(jù)可以調(diào)用 create() 方法谱姓,例如這里我們插入一條新聞數(shù)據(jù):

from elasticsearch import Elasticsearch
 
es = Elasticsearch()
es.indices.create(index='news', ignore=400)
 
data = {'title': '美國留給伊拉克的是個爛攤子嗎', 'url': 'http://view.news.qq.com/zt2011/usa_iraq/index.htm'}
result = es.create(index='news', doc_type='politics', id=1, body=data)
print(result)

這里我們首先聲明了一條新聞數(shù)據(jù)借尿,包括標題和鏈接,然后通過調(diào)用 create() 方法插入了這條數(shù)據(jù)屉来,在調(diào)用 create() 方法時路翻,我們傳入了四個參數(shù),index 參數(shù)代表了索引名稱奶躯,doc_type 代表了文檔類型帚桩,body 則代表了文檔具體內(nèi)容亿驾,id 則是數(shù)據(jù)的唯一標識 ID嘹黔。

運行結(jié)果如下:

{'_index': 'news', '_type': 'politics', '_id': '1', '_version': 1, 'result': 'created', '_shards': {'total': 2, 'successful': 1, 'failed': 0}, '_seq_no': 0, '_primary_term': 1}

結(jié)果中 result 字段為 created,代表該數(shù)據(jù)插入成功。

另外其實我們也可以使用 index() 方法來插入數(shù)據(jù)儡蔓,但與 create() 不同的是郭蕉,create() 方法需要我們指定 id 字段來唯一標識該條數(shù)據(jù),而 index() 方法則不需要喂江,如果不指定 id召锈,會自動生成一個 id,調(diào)用 index() 方法的寫法如下:

es.index(index='news', doc_type='politics', body=data)

create() 方法內(nèi)部其實也是調(diào)用了 index() 方法获询,是對 index() 方法的封裝涨岁。

更新數(shù)據(jù)
更新數(shù)據(jù)也非常簡單,我們同樣需要指定數(shù)據(jù)的 id 和內(nèi)容吉嚣,調(diào)用 update() 方法即可梢薪,代碼如下:

from elasticsearch import Elasticsearch
 
es = Elasticsearch()
data = {
    'title': '美國留給伊拉克的是個爛攤子嗎',
    'url': 'http://view.news.qq.com/zt2011/usa_iraq/index.htm',
    'date': '2020-03-26'
}
result = es.update(index='news', doc_type='politics', body=data, id=1)
print(result)

這里我們?yōu)閿?shù)據(jù)增加了一個日期字段,然后調(diào)用了 update() 方法尝哆,結(jié)果如下:

{'_index': 'news', '_type': 'politics', '_id': '1', '_version': 2, 'result': 'updated', '_shards': {'total': 2, 'successful': 1, 'failed': 0}, '_seq_no': 1, '_primary_term': 1}

可以看到返回結(jié)果中秉撇,result 字段為 updated,即表示更新成功秋泄,另外我們還注意到有一個字段 _version琐馆,這代表更新后的版本號數(shù),2 代表這是第二個版本恒序,因為之前已經(jīng)插入過一次數(shù)據(jù)瘦麸,所以第一次插入的數(shù)據(jù)是版本 1,可以參見上例的運行結(jié)果奸焙,這次更新之后版本號就變成了 2瞎暑,以后每更新一次,版本號都會加 1与帆。

另外更新操作其實利用 index() 方法同樣可以做到了赌,寫法如下:

es.index(index='news', doc_type='politics', body=data, id=1)

可以看到,index() 方法可以代替我們完成兩個操作玄糟,如果數(shù)據(jù)不存在勿她,那就執(zhí)行插入操作,如果已經(jīng)存在阵翎,那就執(zhí)行更新操作逢并,非常方便。

刪除數(shù)據(jù)
如果想刪除一條數(shù)據(jù)可以調(diào)用 delete() 方法郭卫,指定需要刪除的數(shù)據(jù) id 即可砍聊,寫法如下:

from elasticsearch import Elasticsearch
 
es = Elasticsearch()
result = es.delete(index='news', doc_type='politics', id=1)
print(result)

運行結(jié)果如下:

{'_index': 'news', '_type': 'politics', '_id': '1', '_version': 3, 'result': 'deleted', '_shards': {'total': 2, 'successful': 1, 'failed': 0}, '_seq_no': 2, '_primary_term': 1}

可以看到運行結(jié)果中 result 字段為 deleted,代表刪除成功贰军,_version 變成了 3玻蝌,又增加了 1。

查詢數(shù)據(jù)
上面的幾個操作都是非常簡單的操作,普通的數(shù)據(jù)庫如 MongoDB 都是可以完成的俯树,看起來并沒有什么了不起的帘腹,Elasticsearch 更特殊的地方在于其異常強大的檢索功能。

對于中文來說许饿,我們需要安裝一個分詞插件阳欲,這里使用的是 elasticsearch-analysis-ik,GitHub 鏈接為:https://github.com/medcl/elasticsearch-analysis-ik陋率,這里我們使用 Elasticsearch 的另一個命令行工具 elasticsearch-plugin 來安裝,這里安裝的版本是 6.8.6瓦糟,請確保和 Elasticsearch 的版本對應(yīng)起來赊窥,命令如下:

elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.8.6/elasticsearch-analysis-ik-6.8.6.zip

這里的版本號請?zhí)鎿Q成你的 Elasticsearch 的版本號。

安裝之后重新啟動 Elasticsearch 就可以了狸页,它會自動加載安裝好的插件锨能。

首先我們新建一個索引并指定需要分詞的字段,代碼如下:

from elasticsearch import Elasticsearch
 
es = Elasticsearch()
mapping = {
    'properties': {
        'title': {
            'type': 'text',
            'analyzer': 'ik_max_word',
            'search_analyzer': 'ik_max_word'
        }
    }
}
es.indices.delete(index='news', ignore=[400, 404])
es.indices.create(index='news', ignore=400)
result = es.indices.put_mapping(index='news', doc_type='politics', body=mapping)
print(result)

這里我們先將之前的索引刪除了芍耘,然后新建了一個索引址遇,然后更新了它的 mapping 信息,mapping 信息中指定了分詞的字段斋竞,指定了字段的類型 type 為 text倔约,分詞器 analyzer 和 搜索分詞器 search_analyzer 為 ik_max_word,即使用我們剛才安裝的中文分詞插件坝初。如果不指定的話則使用默認的英文分詞器浸剩。

接下來我們插入幾條新的數(shù)據(jù):

datas = [
    {
        'title': '美國留給伊拉克的是個爛攤子嗎',
        'url': 'http://view.news.qq.com/zt2011/usa_iraq/index.htm',
        'date': '2020-03-26'
    },
    {
        'title': '公安部:各地校車將享最高路權(quán)',
        'url': 'http://www.chinanews.com/gn/2011/12-16/3536077.shtml',
        'date': '2020-03-26'
    },
    {
        'title': '中韓漁警沖突調(diào)查:韓警平均每天扣1艘中國漁船',
        'url': 'https://news.qq.com/a/20111216/001044.htm',
        'date': '2020-03-26'
    },
    {
        'title': '中國駐洛杉磯領(lǐng)事館遭亞裔男子槍擊 嫌犯已自首',
        'url': 'http://news.ifeng.com/world/detail_2011_12/16/11372558_0.shtml',
        'date': '2020-03-26'
    }
]
 
for data in datas:
    es.index(index='news', doc_type='politics', body=data)

這里我們指定了四條數(shù)據(jù),都帶有 title鳄袍、url绢要、date 字段,然后通過 index() 方法將其插入 Elasticsearch 中拗小,索引名稱為 news重罪,類型為 politics。

接下來我們根據(jù)關(guān)鍵詞查詢一下相關(guān)內(nèi)容:

result = es.search(index='news', doc_type='politics')
print(result)

可以看到查詢出了所有插入的四條數(shù)據(jù):

{
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 4,
    "max_score": 1.0,
    "hits": [
      {
        "_index": "news",
        "_type": "politics",
        "_id": "c05G9mQBD9BuE5fdHOUT",
        "_score": 1.0,
        "_source": {
          "title": "美國留給伊拉克的是個爛攤子嗎",
          "url": "http://view.news.qq.com/zt2011/usa_iraq/index.htm",
          "date": "2020-03-26"
        }
      },
      {
        "_index": "news",
        "_type": "politics",
        "_id": "dk5G9mQBD9BuE5fdHOUm",
        "_score": 1.0,
        "_source": {
          "title": "中國駐洛杉磯領(lǐng)事館遭亞裔男子槍擊哀九,嫌犯已自首",
          "url": "http://news.ifeng.com/world/detail_2011_12/16/11372558_0.shtml",
          "date": "2020-03-26"
        }
      },
      {
        "_index": "news",
        "_type": "politics",
        "_id": "dU5G9mQBD9BuE5fdHOUj",
        "_score": 1.0,
        "_source": {
          "title": "中韓漁警沖突調(diào)查:韓警平均每天扣1艘中國漁船",
          "url": "https://news.qq.com/a/20111216/001044.htm",
          "date": "2020-03-26"
        }
      },
      {
        "_index": "news",
        "_type": "politics",
        "_id": "dE5G9mQBD9BuE5fdHOUf",
        "_score": 1.0,
        "_source": {
          "title": "公安部:各地校車將享最高路權(quán)",
          "url": "http://www.chinanews.com/gn/2011/12-16/3536077.shtml",
          "date": "2020-03-26"
        }
      }
    ]
  }
}

可以看到返回結(jié)果會出現(xiàn)在 hits 字段里面剿配,然后其中有 total 字段標明了查詢的結(jié)果條目數(shù),還有 max_score 代表了最大匹配分數(shù)阅束。

另外我們還可以進行全文檢索呼胚,這才是體現(xiàn) Elasticsearch 搜索引擎特性的地方:

dsl = {
    'query': {
        'match': {
            'title': '中國 領(lǐng)事館'
        }
    }
}
 
es = Elasticsearch()
result = es.search(index='news', doc_type='politics', body=dsl)
print(json.dumps(result, indent=2, ensure_ascii=False))

這里我們使用 Elasticsearch 支持的 DSL 語句來進行查詢,使用 match 指定全文檢索息裸,檢索的字段是 title蝇更,內(nèi)容是“中國領(lǐng)事館”琢融,搜索結(jié)果如下:

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": 2.546152,
    "hits": [
      {
        "_index": "news",
        "_type": "politics",
        "_id": "dk5G9mQBD9BuE5fdHOUm",
        "_score": 2.546152,
        "_source": {
          "title": "中國駐洛杉磯領(lǐng)事館遭亞裔男子槍擊,嫌犯已自首",
          "url": "http://news.ifeng.com/world/detail_2011_12/16/11372558_0.shtml",
          "date": "2020-03-26"
        }
      },
      {
        "_index": "news",
        "_type": "politics",
        "_id": "dU5G9mQBD9BuE5fdHOUj",
        "_score": 0.2876821,
        "_source": {
          "title": "中韓漁警沖突調(diào)查:韓警平均每天扣1艘中國漁船",
          "url": "https://news.qq.com/a/20111216/001044.htm",
          "date": "2020-03-26"
        }
      }
    ]
  }
}

這里我們看到匹配的結(jié)果有兩條簿寂,第一條的分數(shù)為 2.54,第二條的分數(shù)為 0.28宿亡,這是因為第一條匹配的數(shù)據(jù)中含有“中國”和“領(lǐng)事館”兩個詞常遂,第二條匹配的數(shù)據(jù)中不包含“領(lǐng)事館”,但是包含了“中國”這個詞挽荠,所以也被檢索出來了克胳,但是分數(shù)比較低。

因此可以看出圈匆,檢索時會對對應(yīng)的字段全文檢索漠另,結(jié)果還會按照檢索關(guān)鍵詞的相關(guān)性進行排序,這就是一個基本的搜索引擎雛形跃赚。

另外 Elasticsearch 還支持非常多的查詢方式笆搓,詳情可以參考官方文檔

以上便是對 Elasticsearch 的基本介紹以及 Python 操作 Elasticsearch 的基本用法纬傲。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末满败,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子叹括,更是在濱河造成了極大的恐慌算墨,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件汁雷,死亡現(xiàn)場離奇詭異净嘀,居然都是意外死亡,警方通過查閱死者的電腦和手機侠讯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進店門挖藏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人厢漩,你說我怎么就攤上這事熬苍。” “怎么了袁翁?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵柴底,是天一觀的道長。 經(jīng)常有香客問我粱胜,道長柄驻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任焙压,我火速辦了婚禮鸿脓,結(jié)果婚禮上抑钟,老公的妹妹穿的比我還像新娘。我一直安慰自己野哭,他們只是感情好在塔,可當我...
    茶點故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著拨黔,像睡著了一般蛔溃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上篱蝇,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天贺待,我揣著相機與錄音,去河邊找鬼零截。 笑死麸塞,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的涧衙。 我是一名探鬼主播哪工,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼弧哎!你這毒婦竟也來了正勒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤傻铣,失蹤者是張志新(化名)和其女友劉穎章贞,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體非洲,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡鸭限,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了两踏。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片败京。...
    茶點故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖梦染,靈堂內(nèi)的尸體忽然破棺而出赡麦,到底是詐尸還是另有隱情,我是刑警寧澤帕识,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布泛粹,位于F島的核電站,受9級特大地震影響肮疗,放射性物質(zhì)發(fā)生泄漏晶姊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一伪货、第九天 我趴在偏房一處隱蔽的房頂上張望们衙。 院中可真熱鬧钾怔,春花似錦、人聲如沸蒙挑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽忆蚀。三九已至矾利,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間蜓谋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工炭分, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留桃焕,地道東北人。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓捧毛,卻偏偏與公主長得像观堂,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子呀忧,可洞房花燭夜當晚...
    茶點故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容

  • 一师痕、 什么是 Elasticsearch 想查數(shù)據(jù)就免不了搜索,搜索就離不開搜索引擎而账,百度胰坟、谷歌都是一個非常龐大復(fù)...
    古佛青燈度流年閱讀 1,126評論 1 3
  • 第3章 映射 映射是定義存儲和索引的文檔類型以及字段的過程。索引中的每一個文檔都有一個類型泞辐,每種類型都有它自己的映...
    MR_ChanHwang閱讀 2,306評論 0 1
  • 個人專題目錄 1. Mapping映射入門 1.1 什么是mapping映射 概念:自動或手動為index中的_d...
    Java及SpringBoot閱讀 4,647評論 1 4
  • 我本一潭清凈的水笔横, 你來了, 漣漪起了咐吼, 浪花多了吹缔, 水邊一片盎然, 水亦清锯茄,天空亦明厢塘, 不復(fù)往日冷清。 你走了肌幽,...
    六月豐山閱讀 222評論 0 2
  • 冬天過去了大半,天氣愈加寒冷煮岁。瑟瑟北風劃過我們稚嫰的臉頰讥蔽,好在陽光陪伴涣易,給了淡薄的陽光。 我們在江濱公園的廣場上冶伞,...
    呂childe天閱讀 212評論 0 2