国产成人精品18p,天天干成人网,无码专区狠狠躁天天躁,美女脱精光隐私扒开免费观看

Elasticsearch與Python的對接實(shí)現

發(fā)布時(shí)間:2021-09-04 11:56 來(lái)源:億速云 閱讀:0 作者:chen 欄目: 網(wǎng)絡(luò )安全

這篇文章主要講解了“Elasticsearch與Python的對接實(shí)現”,文中的講解內容簡(jiǎn)單清晰,易于學(xué)習與理解,下面請大家跟著(zhù)小編的思路慢慢深入,一起來(lái)研究和學(xué)習“Elasticsearch與Python的對接實(shí)現”吧!

什么是 Elasticsearch

想查數據就免不了搜索,搜索就離不開(kāi)搜索引擎,百度、谷歌都是一個(gè)非常龐大復雜的搜索引擎,他們幾乎索引了互聯(lián)網(wǎng)上開(kāi)放的所有網(wǎng)頁(yè)和數據。然而對于我們自己的業(yè)務(wù)數據來(lái)說(shuō),肯定就沒(méi)必要用這么復雜的技術(shù)了,如果我們想實(shí)現自己的搜索引擎,方便存儲和檢索,Elasticsearch 就是不二選擇,它是一個(gè)全文搜索引擎,可以快速地儲存、搜索和分析海量數據。

為什么要用 Elasticsearch

Elasticsearch 是一個(gè)開(kāi)源的搜索引擎,建立在一個(gè)全文搜索引擎庫 Apache Lucene? 基礎之上。

那 Lucene 又是什么?Lucene 可能是目前存在的,不論開(kāi)源還是私有的,擁有最先進(jìn),高性能和全功能搜索引擎功能的庫,但也僅僅只是一個(gè)庫。要用上 Lucene,我們需要編寫(xiě) Java 并引用 Lucene 包才可以,而且我們需要對信息檢索有一定程度的理解才能明白 Lucene 是怎么工作的,反正用起來(lái)沒(méi)那么簡(jiǎn)單。

那么為了解決這個(gè)問(wèn)題,Elasticsearch 就誕生了。Elasticsearch 也是使用 Java 編寫(xiě)的,它的內部使用 Lucene 做索引與搜索,但是它的目標是使全文檢索變得簡(jiǎn)單,相當于 Lucene 的一層封裝,它提供了一套簡(jiǎn)單一致的 RESTful API 來(lái)幫助我們實(shí)現存儲和檢索。

所以 Elasticsearch 僅僅就是一個(gè)簡(jiǎn)易版的 Lucene 封裝嗎?那就大錯特錯了,Elasticsearch 不僅僅是 Lucene,并且也不僅僅只是一個(gè)全文搜索引擎。 它可以被下面這樣準確的形容:

  • 一個(gè)分布式的實(shí)時(shí)文檔存儲,每個(gè)字段可以被索引與搜索

  • 一個(gè)分布式實(shí)時(shí)分析搜索引擎

  • 能勝任上百個(gè)服務(wù)節點(diǎn)的擴展,并支持 PB 級別的結構化或者非結構化數據

總之,是一個(gè)相當牛逼的搜索引擎,維基百科、Stack Overflow、GitHub 都紛紛采用它來(lái)做搜索。

Elasticsearch 的安裝

我們可以到 Elasticsearch 的官方網(wǎng)站下載 Elasticsearch:https://www.elastic.co/downloads/elasticsearch,同時(shí)官網(wǎng)也附有安裝說(shuō)明。

首先把安裝包下載下來(lái)并解壓,然后運行 bin/elasticsearch(Mac 或 Linux)或者 bin\elasticsearch.bat (Windows) 即可啟動(dòng) Elasticsearch 了。

我使用的是 Mac,Mac 下個(gè)人推薦使用 Homebrew 安裝:

brew install elasticsearch

Elasticsearch 默認會(huì )在 9200 端口上運行,我們打開(kāi)瀏覽器訪(fǎng)問(wèn)
http://localhost:9200/ 就可以看到類(lèi)似內容:

{
  "name" : "atntrTf",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "e64hkjGtTp6_G2h2Xxdv5g",
  "version" : {
    "number": "6.2.4",
    "build_hash": "ccec39f",
    "build_date": "2018-04-12T20:37:28.497551Z",
    "build_snapshot": false,
    "lucene_version": "7.2.1",
    "minimum_wire_compatibility_version": "5.6.0",
    "minimum_index_compatibility_version": "5.0.0"
  },
  "tagline" : "You Know, for Search"
}

如果看到這個(gè)內容,就說(shuō)明 Elasticsearch 安裝并啟動(dòng)成功了,這里顯示我的 Elasticsearch 版本是 6.2.4 版本,版本很重要,以后安裝一些插件都要做到版本對應才可以。

接下來(lái)我們來(lái)了解一下 Elasticsearch 的基本概念以及和 Python 的對接。

Elasticsearch 相關(guān)概念

在 Elasticsearch 中有幾個(gè)基本的概念,如節點(diǎn)、索引、文檔等等,下面來(lái)分別說(shuō)明一下,理解了這些概念對熟悉 Elasticsearch 是非常有幫助的。

Node 和 Cluster

Elasticsearch 本質(zhì)上是一個(gè)分布式數據庫,允許多臺協(xié)同工作,每臺服務(wù)器可以運行多個(gè) Elasticsearch 實(shí)例。

單個(gè) Elasticsearch 實(shí)例稱(chēng)為一個(gè)節點(diǎn)(Node)。一組節點(diǎn)構成一個(gè)集群(Cluster)。

Index

Elasticsearch 會(huì )索引所有字段,經(jīng)過(guò)處理后寫(xiě)入一個(gè)反向索引(Inverted Index)。查找數據的時(shí)候,直接查找該索引。

所以,Elasticsearch 數據管理的頂層單位就叫做 Index(索引),其實(shí)就相當于 、 等里面的數據庫的概念。另外值得注意的是,每個(gè) Index (即數據庫)的名字必須是小寫(xiě)。

Document

Index 里面單條的記錄稱(chēng)為 Document(文檔)。許多條 Document 構成了一個(gè) Index。

Document 使用 JSON 格式表示,下面是一個(gè)例子。

同一個(gè) Index 里面的 Document,不要求有相同的結構(scheme),但是最好保持相同,這樣有利于提高搜索效率。

Type

Document 可以分組,比如 weather 這個(gè) Index 里面,可以按城市分組(北京和上海),也可以按氣候分組(晴天和雨天)。這種分組就叫做 Type,它是虛擬的邏輯分組,用來(lái)過(guò)濾 Document,類(lèi)似 MySQL 中的數據表,MongoDB 中的 Collection。

不同的 Type 應該有相似的結構(Schema),舉例來(lái)說(shuō),id 字段不能在這個(gè)組是字符串,在另一個(gè)組是數值。這是與的表的一個(gè)區別。性質(zhì)完全不同的數據(比如 products 和 logs)應該存成兩個(gè) Index,而不是一個(gè) Index 里面的兩個(gè) Type(雖然可以做到)。

根據規劃,Elastic 6.x 版只允許每個(gè) Index 包含一個(gè) Type,7.x 版將會(huì )徹底移除 Type。

Fields

即字段,每個(gè) Document 都類(lèi)似一個(gè) JSON 結構,它包含了許多字段,每個(gè)字段都有其對應的值,多個(gè)字段組成了一個(gè) Document,其實(shí)就可以類(lèi)比 MySQL 數據表中的字段。

在 Elasticsearch 中,文檔歸屬于一種類(lèi)型(Type),而這些類(lèi)型存在于索引(Index)中,我們可以畫(huà)一些簡(jiǎn)單的對比圖來(lái)類(lèi)比傳統關(guān)系型數據庫:

Relational DB -> Databases -> Tables -> Rows -> Columns
Elasticsearch -> Indices   -> Types  -> Documents -> Fields

以上就是 Elasticsearch 里面的一些基本概念,通過(guò)和關(guān)系性數據庫的對比更加有助于理解。

Python 對接 Elasticsearch

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

Python 中對接 Elasticsearch 使用的就是一個(gè)同名的庫,安裝方式非常簡(jiǎn)單:

pip3 install elasticsearch

官方文檔是:https://elasticsearch-py.readthedocs.io/,所有的用法都可以在里面查到,文章后面的內容也是基于官方文檔來(lái)的。

創(chuàng )建 Index

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

from elasticsearch import Elasticsearch

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

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

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

返回結果是 JSON 格式,其中的 acknowledged 字段表示創(chuàng )建操作執行成功。

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

{'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 參數為 400,這說(shuō)明如果返回結果是 400 的話(huà),就忽略這個(gè)錯誤不會(huì )報錯,程序不會(huì )執行拋出異常。

假如我們不加 ignore 這個(gè)參數的話(huà):

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

再次執行就會(huì )報錯了:

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')

這樣程序的執行就會(huì )出現問(wèn)題,所以說(shuō),我們需要善用 ignore 參數,把一些意外情況排除,這樣可以保證程序的正常執行而不會(huì )中斷。

刪除 Index

刪除 Index 也是類(lèi)似的,代碼如下:

from elasticsearch import Elasticsearch

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

這里也是使用了 ignore 參數,來(lái)忽略 Index 不存在而刪除失敗導致程序中斷的問(wèn)題。

如果刪除成功,會(huì )輸出如下結果:

{'acknowledged': True}

如果 Index 已經(jīng)被刪除,再執行刪除則會(huì )輸出如下結果:

{'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}

這個(gè)結果表明當前 Index 不存在,刪除失敗,返回的結果同樣是 JSON,狀態(tài)碼是 400,但是由于我們添加了 ignore 參數,忽略了 400 狀態(tài)碼,因此程序正常執行輸出 JSON 結果,而不是拋出異常。

插入數據

Elasticsearch 就像 MongoDB 一樣,在插入數據的時(shí)候可以直接插入結構化字典數據,插入數據可以調用 create() 方法,例如這里我們插入一條新聞數據:

from elasticsearch import Elasticsearch

es = Elasticsearch()
es.indices.create(index='news', ignore=400)

data = {'title': '美國留給伊拉克的是個(gè)爛攤子嗎', '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)

這里我們首先聲明了一條新聞數據,包括標題和鏈接,然后通過(guò)調用 create() 方法插入了這條數據,在調用 create() 方法時(shí),我們傳入了四個(gè)參數,index 參數代表了索引名稱(chēng),doc_type 代表了文檔類(lèi)型,body 則代表了文檔具體內容,id 則是數據的唯一標識 ID。

運行結果如下:

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

結果中 result 字段為 created,代表該數據插入成功。

另外其實(shí)我們也可以使用 index() 方法來(lái)插入數據,但與 create() 不同的是,create() 方法需要我們指定 id 字段來(lái)唯一標識該條數據,而 index() 方法則不需要,如果不指定 id,會(huì )自動(dòng)生成一個(gè) id,調用 index() 方法的寫(xiě)法如下:

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

create() 方法內部其實(shí)也是調用了 index() 方法,是對 index() 方法的封裝。

更新數據

更新數據也非常簡(jiǎn)單,我們同樣需要指定數據的 id 和內容,調用 update() 方法即可,代碼如下:

from elasticsearch import Elasticsearch

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

這里我們?yōu)閿祿黾恿艘粋€(gè)日期字段,然后調用了 update() 方法,結果如下:

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

可以看到返回結果中,result 字段為 updated,即表示更新成功,另外我們還注意到有一個(gè)字段 _version,這代表更新后的版本號數,2 代表這是第二個(gè)版本,因為之前已經(jīng)插入過(guò)一次數據,所以第一次插入的數據是版本 1,可以參見(jiàn)上例的運行結果,這次更新之后版本號就變成了 2,以后每更新一次,版本號都會(huì )加 1。

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

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

可以看到,index() 方法可以代替我們完成兩個(gè)操作,如果數據不存在,那就執行插入操作,如果已經(jīng)存在,那就執行更新操作,非常方便。

刪除數據

如果想刪除一條數據可以調用 delete() 方法,指定需要刪除的數據 id 即可,寫(xiě)法如下:

from elasticsearch import Elasticsearch

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

運行結果如下:

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

可以看到運行結果中 result 字段為 deleted,代表刪除成功,_version 變成了 3,又增加了 1。

查詢(xún)數據

上面的幾個(gè)操作都是非常簡(jiǎn)單的操作,普通的數據庫如 MongoDB 都是可以完成的,看起來(lái)并沒(méi)有什么了不起的,Elasticsearch 更特殊的地方在于其異常強大的檢索功能。

對于中文來(lái)說(shuō),我們需要安裝一個(gè)分詞插件,這里使用的是 elasticsearch-analysis-ik,GitHub 鏈接為:https://github.com/medcl/elasticsearch-analysis-ik,這里我們使用 Elasticsearch 的另一個(gè)命令行工具 elasticsearch-plugin 來(lái)安裝,這里安裝的版本是 6.2.4,請確保和 Elasticsearch 的版本對應起來(lái),命令如下:

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

這里的版本號請替換成你的 Elasticsearch 的版本號。

安裝之后重新啟動(dòng) Elasticsearch 就可以了,它會(huì )自動(dòng)加載安裝好的插件。

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

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)

這里我們先將之前的索引刪除了,然后新建了一個(gè)索引,然后更新了它的 mapping 信息,mapping 信息中指定了分詞的字段,指定了字段的類(lèi)型 type 為 text,分詞器 analyzer 和 搜索分詞器 search_analyzer 為 ik_max_word,即使用我們剛才安裝的中文分詞插件。如果不指定的話(huà)則使用默認的英文分詞器。

接下來(lái)我們插入幾條新的數據:

datas = [
    {
        'title': '美國留給伊拉克的是個(gè)爛攤子嗎',
        'url': 'http://view.news.qq.com/zt2011/usa_iraq/index.htm',
        'date': '2011-12-16'
    },
    {
        'title': '公安部:各地校車(chē)將享最高路權',
        'url': 'http://www.chinanews.com/gn/2011/12-16/3536077.shtml',
        'date': '2011-12-16'
    },
    {
        'title': '中韓漁警沖突調查:韓警平均每天扣1艘中國漁船',
        'url': 'https://news.qq.com/a/20111216/001044.htm',
        'date': '2011-12-17'
    },
    {
        'title': '中國駐洛杉磯領(lǐng)事館遭亞裔男子槍擊 嫌犯已自首',
        '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', doc_type='politics', body=data)

這里我們指定了四條數據,都帶有 title、url、date 字段,然后通過(guò) index() 方法將其插入 Elasticsearch 中,索引名稱(chēng)為 news,類(lèi)型為 politics。

接下來(lái)我們根據關(guān)鍵詞查詢(xún)一下相關(guān)內容:

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

可以看到查詢(xún)出了所有插入的四條數據:

{
  "took": ,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": ,
    "failed": 
  },
  "hits": {
    "total": 4,
    "max_score": 1.0,
    "hits": [
      {
        "_index": "news",
        "_type": "politics",
        "_id": "c05G9mQBD9BuE5fdHOUT",
        "_score": 1.0,
        "_source": {
          "title": "美國留給伊拉克的是個(gè)爛攤子嗎",
          "url": "http://view.news.qq.com/zt2011/usa_iraq/index.htm",
          "date": "2011-12-16"
        }
      },
      {
        "_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": "2011-12-18"
        }
      },
      {
        "_index": "news",
        "_type": "politics",
        "_id": "dU5G9mQBD9BuE5fdHOUj",
        "_score": 1.0,
        "_source": {
          "title": "中韓漁警沖突調查:韓警平均每天扣1艘中國漁船",
          "url": "https://news.qq.com/a/20111216/001044.htm",
          "date": "2011-12-17"
        }
      },
      {
        "_index": "news",
        "_type": "politics",
        "_id": "dE5G9mQBD9BuE5fdHOUf",
        "_score": 1.0,
        "_source": {
          "title": "公安部:各地校車(chē)將享最高路權",
          "url": "http://www.chinanews.com/gn/2011/12-16/3536077.shtml",
          "date": "2011-12-16"
        }
      }
    ]
  }
}

可以看到返回結果會(huì )出現在 hits 字段里面,然后其中有 total 字段標明了查詢(xún)的結果條目數,還有 max_score 代表了最大匹配分數。

另外我們還可以進(jì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 語(yǔ)句來(lái)進(jìn)行查詢(xún),使用 match 指定全文檢索,檢索的字段是 title,內容是“中國領(lǐng)事館”,搜索結果如下:

{
  "took": 1,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": ,
    "failed": 
  },
  "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": "2011-12-18"
        }
      },
      {
        "_index": "news",
        "_type": "politics",
        "_id": "dU5G9mQBD9BuE5fdHOUj",
        "_score": 0.2876821,
        "_source": {
          "title": "中韓漁警沖突調查:韓警平均每天扣1艘中國漁船",
          "url": "https://news.qq.com/a/20111216/001044.htm",
          "date": "2011-12-17"
        }
      }
    ]
  }
}

這里我們看到匹配的結果有兩條,第一條的分數為 2.54,第二條的分數為 0.28,這是因為第一條匹配的數據中含有“中國”和“領(lǐng)事館”兩個(gè)詞,第二條匹配的數據中不包含“領(lǐng)事館”,但是包含了“中國”這個(gè)詞,所以也被檢索出來(lái)了,但是分數比較低。

因此可以看出,檢索時(shí)會(huì )對對應的字段全文檢索,結果還會(huì )按照檢索關(guān)鍵詞的相關(guān)性進(jìn)行排序,這就是一個(gè)基本的搜索引擎雛形。


免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自互聯(lián)網(wǎng)轉載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權請聯(lián)系QQ:712375056 進(jìn)行舉報,并提供相關(guān)證據,一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容。

欧美成人精品高清在线观看| 五月丁香啪啪| 国产成人无码一二三区视频| 欧洲AV成本人在线观看免费| 亚洲AV无码成人精品区H| 国产在线观看码高清视频|