Elasticsearch與Python是如何對接實現(xiàn)的-創(chuàng)新互聯(lián)

創(chuàng)新互聯(lián)www.cdcxhl.cn八線動態(tài)BGP香港云服務器提供商,新人活動買多久送多久,劃算不套路!

成都創(chuàng)新互聯(lián)服務項目包括北侖網站建設、北侖網站制作、北侖網頁制作以及北侖網絡營銷策劃等。多年來,我們專注于互聯(lián)網行業(yè),利用自身積累的技術優(yōu)勢、行業(yè)經驗、深度合作伙伴關系等,向廣大中小型企業(yè)、政府機構等提供互聯(lián)網行業(yè)的解決方案,北侖網站推廣取得了明顯的社會效益與經濟效益。目前,我們服務的客戶以成都為中心已經輻射到北侖省份的部分城市,未來相信會繼續(xù)擴大服務區(qū)域并繼續(xù)獲得客戶的支持與信任!

小編給大家分享一下Elasticsearch與Python是如何對接實現(xiàn)的,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

什么是 Elasticsearch

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

為什么要用 Elasticsearch

Elasticsearch 是一個開源的搜索引擎,建立在一個全文搜索引擎庫 Apache Lucene? 基礎之上。

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

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

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

·一個分布式的實時文檔存儲,每個字段可以被索引與搜索

·一個分布式實時分析搜索引擎

·能勝任上百個服務節(jié)點的擴展,并支持 PB 級別的結構化或者非結構化數(shù)據

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

Elasticsearch 的安裝

我們可以到 Elasticsearch 的官方網站下載 Elasticsearch:https://www.elastic.co/downloads/elasticsearch,同時官網也附有安裝說明。

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

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

brew install elasticsearch

Elasticsearch 默認會在 9200 端口上運行,我們打開瀏覽器訪問

http://localhost:9200/ 就可以看到類似內容:

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

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

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

Elasticsearch 相關概念

在 Elasticsearch 中有幾個基本的概念,如節(jié)點、索引、文檔等等,下面來分別說明一下,理解了這些概念對熟悉 Elasticsearch 是非常有幫助的。

Node 和 Cluster

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

單個 Elasticsearch 實例稱為一個節(jié)點(Node)。一組節(jié)點構成一個集群(Cluster)。

Index

Elasticsearch 會索引所有字段,經過處理后寫入一個反向索引(Inverted Index)。查找數(shù)據的時候,直接查找該索引。

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

Document

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

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

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

Type

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

不同的 Type 應該有相似的結構(Schema),舉例來說,id 字段不能在這個組是字符串,在另一個組是數(shù)值。這是與關系型數(shù)據庫的表的一個區(qū)別。性質完全不同的數(shù)據(比如 products 和 logs)應該存成兩個 Index,而不是一個 Index 里面的兩個 Type(雖然可以做到)。

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

Fields

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

在 Elasticsearch 中,文檔歸屬于一種類型(Type),而這些類型存在于索引(Index)中,我們可以畫一些簡單的對比圖來類比傳統(tǒng)關系型數(shù)據庫:

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

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

Python 對接 Elasticsearch

Elasticsearch 實際上提供了一系列 Restful API 來進行存取和查詢操作,我們可以使用 curl 等命令來進行操作,但畢竟命令行模式沒那么方便,所以這里我們就直接介紹利用 Python 來對接 Elasticsearch 的相關方法。

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

pip3 install elasticsearch

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

創(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)建成功,會返回如下結果:

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

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

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

{'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 已經存在了。

注意這里我們的代碼里面使用了 ignore 參數(shù)為 400,這說明如果返回結果是 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 不存在而刪除失敗導致程序中斷的問題。

如果刪除成功,會輸出如下結果:

{'acknowledged': True}

如果 Index 已經被刪除,再執(zhí)行刪除則會輸出如下結果:

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

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

插入數(shù)據

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

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ù)據,包括標題和鏈接,然后通過調用 create() 方法插入了這條數(shù)據,在調用 create() 方法時,我們傳入了四個參數(shù),index 參數(shù)代表了索引名稱,doc_type 代表了文檔類型,body 則代表了文檔具體內容,id 則是數(shù)據的唯一標識 ID。

運行結果如下:

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

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

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

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

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

更新數(shù)據

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

from elasticsearch import Elasticsearch
es = Elasticsearch()
data = {
    'title': '美國留給伊拉克的是個爛攤子嗎',
    '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)閿?shù)據增加了一個日期字段,然后調用了 update() 方法,結果如下:

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

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

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

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

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

刪除數(shù)據

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

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': 0}, '_seq_no': 2, '_primary_term': 1}

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

查詢數(shù)據

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

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

elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.2.4 
/elasticsearch-analysis-ik-6.2.4.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ù)據:

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': '中韓漁警沖突調查:韓警平均每天扣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', doc_type='politics', body=data)

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

接下來我們根據關鍵詞查詢一下相關內容:

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

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

{
  "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": "2011-12-16"
        }
      },
      {
        "_index": "news",
        "_type": "politics",
        "_id": "dk5G9mQBD9BuE5fdHOUm",
        "_score": 1.0,
        "_source": {
          "title": "中國駐洛杉磯領事館遭亞裔男子槍擊,嫌犯已自首",
          "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": "公安部:各地校車將享最高路權",
          "url": "http://www.chinanews.com/gn/2011/12-16/3536077.shtml",
          "date": "2011-12-16"
        }
      }
    ]
  }
}

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

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

dsl = {
    'query': {
        'match': {
            'title': '中國 領事館'
        }
    }
}
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,內容是“中國領事館”,搜索結果如下:

{
  "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": "中國駐洛杉磯領事館遭亞裔男子槍擊,嫌犯已自首",
          "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"
        }
      }
    ]
  }
}

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

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

以上是Elasticsearch與Python是如何對接實現(xiàn)的的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注創(chuàng)新互聯(lián)-成都網站建設公司行業(yè)資訊頻道!

標題名稱:Elasticsearch與Python是如何對接實現(xiàn)的-創(chuàng)新互聯(lián)
標題鏈接:http://muchs.cn/article10/ceeggo.html

成都網站建設公司_創(chuàng)新互聯(lián),為您提供網站營銷、網站制作外貿網站建設、軟件開發(fā)、響應式網站、外貿建站

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)

成都定制網站網頁設計