elasticsearch 的 python API

導入 es

from elasticsearch import Elasticsearch

創(chuàng)建索引

es = Elasticsearch()
 
result = es.indices.create(index='news', ignore=400)
print(result)
{'error': {'root_cause': [{'type': 'resource_already_exists_exception', 'reason': 'index [news/habhrfkzSey5_GR-WmZPYA] already exists', 'index_uuid': 'habhrfkzSey5_GR-WmZPYA', 'index': 'news'}], 'type': 'resource_already_exists_exception', 'reason': 'index [news/habhrfkzSey5_GR-WmZPYA] already exists', 'index_uuid': 'habhrfkzSey5_GR-WmZPYA', 'index': 'news'}, 'status': 400}

其中的 acknowledged 字段表示創(chuàng)建操作執(zhí)行成功

重復創(chuàng)建索引,會引發(fā) 400 錯誤,因此我們需要 ignore 參數(shù)來屏蔽 400 錯誤

es = Elasticsearch()
 
result = es.indices.create(index='news', ignore=400)
print(result)
{'error': {'root_cause': [{'type': 'resource_already_exists_exception', 'reason': 'index [news/habhrfkzSey5_GR-WmZPYA] already exists', 'index_uuid': 'habhrfkzSey5_GR-WmZPYA', 'index': 'news'}], 'type': 'resource_already_exists_exception', 'reason': 'index [news/habhrfkzSey5_GR-WmZPYA] already exists', 'index_uuid': 'habhrfkzSey5_GR-WmZPYA', 'index': 'news'}, 'status': 400}

刪除索引

es = Elasticsearch()
 
result = es.indices.delete(index='news', ignore=[400, 404])
print(result)
{'acknowledged': True}

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

es = Elasticsearch()
 
result = es.indices.delete(index='faq', ignore=[400, 404])
print(result)
{'acknowledged': True}

插入數(shù)據(jù)

Elasticsearch 就像 MongoDB 一樣,在插入數(shù)據(jù)的時候可以直接插入結構化字典數(shù)據(jù)恍涂,插入數(shù)據(jù)可以調(diào)用 create() 方法

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='faq', id=1, body=data)
print(result)
{'_index': 'news', '_type': 'faq', '_id': '1', '_version': 1, 'result': 'created', '_shards': {'total': 2, 'successful': 1, 'failed': 0}, '_seq_no': 0, '_primary_term': 1}

首先聲明了一條新聞數(shù)據(jù) data,包括標題和鏈接植榕,然后通過調(diào)用 create() 方法插入了這條數(shù)據(jù)再沧,在調(diào)用 create() 方法時,我們傳入了四個參數(shù)尊残,index 參數(shù)代表了索引名稱炒瘸,doc_type 代表了文檔類型,body 則代表了文檔具體內(nèi)容寝衫,id 則是數(shù)據(jù)的唯一標識 ID

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

我們也可以使用 index() 方法來插入數(shù)據(jù),但與 create() 不同的是竞端,create() 方法需要我們指定 id 字段來唯一標識該條數(shù)據(jù)屎即,而 index() 方法則不需要,如果不指定 id事富,會自動生成一個 id

es.index(index='news', body=data)
{'_index': 'news',
 '_type': '_doc',
 '_id': '33Fm1W4BMbliRpYyFApv',
 '_version': 1,
 'result': 'created',
 '_shards': {'total': 2, 'successful': 1, 'failed': 0},
 '_seq_no': 1,
 '_primary_term': 1}

create() 方法內(nèi)部其實也是調(diào)用了 index() 方法技俐,是對 index() 方法的封裝

更新數(shù)據(jù)

更新數(shù)據(jù)需要指定數(shù)據(jù)的 id 和內(nèi)容,調(diào)用 update() 方法即可
不知道為什么一直會報錯统台,沒想明白原因雕擂,求大佬們指點迷津

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

RequestError                              Traceback (most recent call last)

<ipython-input-9-769542d9ad85> in <module>
      2 
      3 data = {'title': '美國留給伊拉克的是個爛攤子嗎', 'url': 'http://view.news.qq.com/zt2011/usa_iraq/index.htm', 'date': '2019'}
----> 4 result = es.update(index='news', doc_type='faq', body=data, id=1)
      5 print(result)


/usr/local/lib/python3.7/site-packages/elasticsearch/client/utils.py in _wrapped(*args, **kwargs)
     82                 if p in kwargs:
     83                     params[p] = kwargs.pop(p)
---> 84             return func(*args, params=params, **kwargs)
     85 
     86         return _wrapped


/usr/local/lib/python3.7/site-packages/elasticsearch/client/__init__.py in update(self, index, id, doc_type, body, params)
    656                 raise ValueError("Empty value passed for a required argument.")
    657         return self.transport.perform_request(
--> 658             "POST", _make_path(index, doc_type, id, "_update"), params=params, body=body
    659         )
    660 


/usr/local/lib/python3.7/site-packages/elasticsearch/transport.py in perform_request(self, method, url, headers, params, body)
    356                     headers=headers,
    357                     ignore=ignore,
--> 358                     timeout=timeout,
    359                 )
    360 


/usr/local/lib/python3.7/site-packages/elasticsearch/connection/http_urllib3.py in perform_request(self, method, url, params, body, timeout, ignore, headers)
    255                 method, full_url, url, body, duration, response.status, raw_data
    256             )
--> 257             self._raise_error(response.status, raw_data)
    258 
    259         self.log_request_success(


/usr/local/lib/python3.7/site-packages/elasticsearch/connection/base.py in _raise_error(self, status_code, raw_data)
    180 
    181         raise HTTP_EXCEPTIONS.get(status_code, TransportError)(
--> 182             status_code, error_message, additional_info
    183         )
    184 


RequestError: RequestError(400, 'x_content_parse_exception', '[1:2] [UpdateRequest] unknown field [title], parser not found')

刪除數(shù)據(jù)

刪除一條數(shù)據(jù)可以調(diào)用 delete() 方法,指定需要刪除的數(shù)據(jù) id 即可

es = Elasticsearch()
 
result = es.delete(index='news', id=1)
print(result)
{'_index': 'news', '_type': '_doc', '_id': '1', '_version': 2, 'result': 'deleted', '_shards': {'total': 2, 'successful': 1, 'failed': 0}, '_seq_no': 2, '_primary_term': 1}

查詢數(shù)據(jù)

對于中文來說贱勃,我們需要安裝一個分詞插件井赌,這里使用的是 elasticsearch-analysis-ik谤逼,GitHub 鏈接為:https://github.com/medcl/elasticsearch-analysis-ik ,這里我們使用 Elasticsearch 的另一個命令行工具 elasticsearch-plugin 來安裝仇穗,這里安裝的版本是 7.0.1流部,請確保和 Elasticsearch 的版本對應起來,命令如下:

elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.0.1/elasticsearch

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

安裝之后重新啟動 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='faq', body=mapping, include_type_name=True)
print(result)
{'acknowledged': True}

這里我們先將之前的索引刪除了枝冀,然后新建了一個索引,然后更新了它的 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': '2011-12-16'
    },
    {
        'title': '公安部:各地校車將享最高路權',
        'url': 'http://www.chinanews.com/gn/2011/12-16/3536077.shtml',
        'date': '2011-12-16'
    }, 
    { 
        'title': '中韓漁警沖突調(diào)查:韓警平均每天扣1艘中國漁船', 
        'url': 'https://news.qq.com/a/20111216/001044.htm',
        'date': '2011-12-17'
    },
    {
        'title': '中國駐洛杉磯領事館遭亞裔男子槍擊 嫌犯已自首',
        'url': 'http://news.ifeng.com/world/detail_2011_12/16/11372558_0.shtml',
        'date': '2011-12-18'
    }
]

for data in datas:
    es.index(index='news', body=data)

根據(jù)關鍵詞查詢一下相關內(nèi)容

result = es.search(index='news')
print(result)
{'took': 2, 'timed_out': False, '_shards': {'total': 1, 'successful': 1, 'skipped': 0, 'failed': 0}, 'hits': {'total': {'value': 4, 'relation': 'eq'}, 'max_score': 1.0, 'hits': [{'_index': 'news', '_type': 'faq', '_id': '4HFm1W4BMbliRpYyaAqj', '_score': 1.0, '_source': {'title': '美國留給伊拉克的是個爛攤子嗎', 'url': 'http://view.news.qq.com/zt2011/usa_iraq/index.htm', 'date': '2011-12-16'}}, {'_index': 'news', '_type': 'faq', '_id': '4XFm1W4BMbliRpYyaQoE', '_score': 1.0, '_source': {'title': '公安部:各地校車將享最高路權', 'url': 'http://www.chinanews.com/gn/2011/12-16/3536077.shtml', 'date': '2011-12-16'}}, {'_index': 'news', '_type': 'faq', '_id': '4nFm1W4BMbliRpYyaQoc', '_score': 1.0, '_source': {'title': '中韓漁警沖突調(diào)查:韓警平均每天扣1艘中國漁船', 'url': 'https://news.qq.com/a/20111216/001044.htm', 'date': '2011-12-17'}}, {'_index': 'news', '_type': 'faq', '_id': '43Fm1W4BMbliRpYyaQo6', '_score': 1.0, '_source': {'title': '中國駐洛杉磯領事館遭亞裔男子槍擊 嫌犯已自首', 'url': 'http://news.ifeng.com/world/detail_2011_12/16/11372558_0.shtml', 'date': '2011-12-18'}}]}}

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

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

使用 Elasticsearch 支持的 DSL 語句來進行查詢糙臼,使用 match 指定全文檢索焕妙,檢索的字段是 title,內(nèi)容是“中國領事館”弓摘,搜索結果如下

import json

dsl = {
    'query': {
        'match': {
            'title': '中國領事館'
        }
    }
}
 
es = Elasticsearch()
result = es.search(index='news', body=dsl)
print(json.dumps(result, indent=2, ensure_ascii=False))
{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 3.7446182,
    "hits": [
      {
        "_index": "news",
        "_type": "faq",
        "_id": "43Fm1W4BMbliRpYyaQo6",
        "_score": 3.7446182,
        "_source": {
          "title": "中國駐洛杉磯領事館遭亞裔男子槍擊 嫌犯已自首",
          "url": "http://news.ifeng.com/world/detail_2011_12/16/11372558_0.shtml",
          "date": "2011-12-18"
        }
      },
      {
        "_index": "news",
        "_type": "faq",
        "_id": "4nFm1W4BMbliRpYyaQoc",
        "_score": 0.60291106,
        "_source": {
          "title": "中韓漁警沖突調(diào)查:韓警平均每天扣1艘中國漁船",
          "url": "https://news.qq.com/a/20111216/001044.htm",
          "date": "2011-12-17"
        }
      }
    ]
  }
}

這里我們看到匹配的結果有兩條,第一條的分數(shù)為 3.99痕届,第二條的分數(shù)為 0.64韧献,這是因為第一條匹配的數(shù)據(jù)中含有“中國”和“領事館”兩個詞,第二條匹配的數(shù)據(jù)中不包含“領事館”研叫,但是包含了“中國”這個詞锤窑,所以也被檢索出來了,但是分數(shù)比較低嚷炉。

因此可以看出渊啰,檢索時會對對應的字段全文檢索,結果還會按照檢索關鍵詞的相關性進行排序申屹,這就是一個基本的搜索引擎雛形

參考:https://blog.csdn.net/devcloud/article/details/91446259

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末绘证,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子哗讥,更是在濱河造成了極大的恐慌嚷那,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件杆煞,死亡現(xiàn)場離奇詭異魏宽,居然都是意外死亡腐泻,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門队询,熙熙樓的掌柜王于貴愁眉苦臉地迎上來派桩,“玉大人,你說我怎么就攤上這事蚌斩∶螅” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵凳寺,是天一觀的道長鸭津。 經(jīng)常有香客問我,道長肠缨,這世上最難降的妖魔是什么逆趋? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮晒奕,結果婚禮上闻书,老公的妹妹穿的比我還像新娘。我一直安慰自己脑慧,他們只是感情好魄眉,可當我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著闷袒,像睡著了一般坑律。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上囊骤,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天晃择,我揣著相機與錄音,去河邊找鬼也物。 笑死宫屠,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的滑蚯。 我是一名探鬼主播浪蹂,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼告材!你這毒婦竟也來了坤次?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤斥赋,失蹤者是張志新(化名)和其女友劉穎浙踢,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灿渴,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡洛波,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年胰舆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蹬挤。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡缚窿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出焰扳,到底是詐尸還是另有隱情倦零,我是刑警寧澤,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布吨悍,位于F島的核電站扫茅,受9級特大地震影響,放射性物質發(fā)生泄漏育瓜。R本人自食惡果不足惜葫隙,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望躏仇。 院中可真熱鬧恋脚,春花似錦、人聲如沸焰手。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽书妻。三九已至船响,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間躲履,已是汗流浹背灿意。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留崇呵,地道東北人。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓馅袁,卻偏偏與公主長得像域慷,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子汗销,可洞房花燭夜當晚...
    茶點故事閱讀 45,107評論 2 356