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

溫馨提示×

溫馨提示×

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

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

Elasticsearch與Python的對接實現

發布時間:2021-08-25 10:42:52 來源:億速云 閱讀:305 作者:chen 欄目:網絡安全

這篇文章主要講解了“Elasticsearch與Python的對接實現”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Elasticsearch與Python的對接實現”吧!

什么是 Elasticsearch

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

為什么要用 Elasticsearch

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

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

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

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

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

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

  • 能勝任上百個服務節點的擴展,并支持 PB 級別的結構化或者非結構化數據

總之,是一個相當牛逼的搜索引擎,維基百科、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 中有幾個基本的概念,如節點、索引、文檔等等,下面來分別說明一下,理解了這些概念對熟悉 Elasticsearch 是非常有幫助的。

Node 和 Cluster

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

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

Index

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

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

Document

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

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

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

Type

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

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

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

Fields

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

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

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

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

Python 對接 Elasticsearch

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

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

pip3 install elasticsearch

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

創建 Index

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

from elasticsearch import Elasticsearch

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

如果創建成功,會返回如下結果:

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

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

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

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

它提示創建失敗,status 狀態碼是 400,錯誤原因是 Index 已經存在了。

注意這里我們的代碼里面使用了 ignore 參數為 400,這說明如果返回結果是 400 的話,就忽略這個錯誤不會報錯,程序不會執行拋出異常。

假如我們不加 ignore 這個參數的話:

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

再次執行就會報錯了:

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

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

刪除 Index

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

from elasticsearch import Elasticsearch

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

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

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

{'acknowledged': True}

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

{'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,狀態碼是 400,但是由于我們添加了 ignore 參數,忽略了 400 狀態碼,因此程序正常執行輸出 JSON 結果,而不是拋出異常。

插入數據

Elasticsearch 就像 MongoDB 一樣,在插入數據的時候可以直接插入結構化字典數據,插入數據可以調用 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='politics', id=1, body=data)
print(result)

這里我們首先聲明了一條新聞數據,包括標題和鏈接,然后通過調用 create() 方法插入了這條數據,在調用 create() 方法時,我們傳入了四個參數,index 參數代表了索引名稱,doc_type 代表了文檔類型,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,代表該數據插入成功。

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

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

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

更新數據

更新數據也非常簡單,我們同樣需要指定數據的 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)

這里我們為數據增加了一個日期字段,然后調用了 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,即表示更新成功,另外我們還注意到有一個字段 _version,這代表更新后的版本號數,2 代表這是第二個版本,因為之前已經插入過一次數據,所以第一次插入的數據是版本 1,可以參見上例的運行結果,這次更新之后版本號就變成了 2,以后每更新一次,版本號都會加 1。

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

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

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

刪除數據

如果想刪除一條數據可以調用 delete() 方法,指定需要刪除的數據 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': }, '_seq_no': 2, '_primary_term': 1}

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

查詢數據

上面的幾個操作都是非常簡單的操作,普通的數據庫如 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

這里的版本號請替換成你的 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,即使用我們剛才安裝的中文分詞插件。如果不指定的話則使用默認的英文分詞器。

接下來我們插入幾條新的數據:

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)

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

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

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

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

{
  "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": "美國留給伊拉克的是個爛攤子嗎",
          "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"
        }
      }
    ]
  }
}

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

另外我們還可以進行全文檢索,這才是體現 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": ,
    "failed": 
  },
  "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"
        }
      }
    ]
  }
}

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

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


感謝各位的閱讀,以上就是“Elasticsearch與Python的對接實現”的內容了,經過本文的學習后,相信大家對Elasticsearch與Python的對接實現這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

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

AI

会宁县| 广州市| 寻甸| 五莲县| 咸宁市| 九寨沟县| 德昌县| 英德市| 平顶山市| 区。| 黑水县| 金寨县| 苏州市| 临洮县| 台前县| 襄垣县| 长寿区| 葫芦岛市| 航空| 广元市| 准格尔旗| 洛浦县| 石门县| 定州市| 敦化市| 信宜市| 日土县| 台南市| 嘉善县| 克山县| 武强县| 浮山县| 牙克石市| 博兴县| 灌云县| 武平县| 抚州市| 定远县| 宣化县| 盐源县| 九江县|