使用Python操作Elasticsearch數(shù)據(jù)索引的教程
Elasticsearch是一個分布式、Restful的搜索及分析服務器,Apache Solr一樣,它也是基于Lucence的索引服務器,但我認為Elasticsearch對比Solr的優(yōu)點在于:
- 輕量級:安裝啟動方便,下載文件之后一條命令就可以啟動;
- Schema free:可以向服務器提交任意結構的JSON對象,Solr中使用schema.xml指定了索引結構;
- 多索引文件支持:使用不同的index參數(shù)就能創(chuàng)建另一個索引文件,Solr中需要另行配置;
- 分布式:Solr Cloud的配置比較復雜。
環(huán)境搭建
啟動Elasticsearch,訪問端口在9200,通過瀏覽器可以查看到返回的JSON數(shù)據(jù),Elasticsearch提交和返回的數(shù)據(jù)格式都是JSON.
>> bin/elasticsearch -f
安裝官方提供的Python API,在OS X上安裝后出現(xiàn)一些Python運行錯誤,是因為setuptools版本太舊引起的,刪除重裝后恢復正常。
>> pip install elasticsearch
索引操作
對于單條索引,可以調(diào)用create或index方法。
from datetime import datetime from elasticsearch import Elasticsearch es = Elasticsearch() #create a localhost server connection, or Elasticsearch("ip") es.create(index="test-index", doc_type="test-type", id=1, body={"any":"data", "timestamp": datetime.now()})
Elasticsearch批量索引的命令是bulk,目前Python API的文檔示例較少,花了不少時間閱讀源代碼才弄清楚批量索引的提交格式。
from datetime import datetime from elasticsearch import Elasticsearch from elasticsearch import helpers es = Elasticsearch("10.18.13.3") j = 0 count = int(df[0].count()) actions = [] while (j < count): action = { "_index": "tickets-index", "_type": "tickets", "_id": j + 1, "_source": { "crawaldate":df[0][j], "flight":df[1][j], "price":float(df[2][j]), "discount":float(df[3][j]), "date":df[4][j], "takeoff":df[5][j], "land":df[6][j], "source":df[7][j], "timestamp": datetime.now()} } actions.append(action) j += 1 if (len(actions) == 500000): helpers.bulk(es, actions) del actions[0:len(actions)] if (len(actions) > 0): helpers.bulk(es, actions) del actions[0:len(actions)]
在這里發(fā)現(xiàn)Python API序列化JSON時對數(shù)據(jù)類型支撐比較有限,原始數(shù)據(jù)使用的NumPy.Int32必須轉換為int才能索引。此外,現(xiàn)在的bulk操作默認是每次提交500條數(shù)據(jù),我修改為5000甚至50000進行測試,會有索引不成功的情況。
#helpers.py source code def streaming_bulk(client, actions, chunk_size=500, raise_on_error=False, expand_action_callback=expand_action, **kwargs): actions = map(expand_action_callback, actions) # if raise on error is set, we need to collect errors per chunk before raising them errors = [] while True: chunk = islice(actions, chunk_size) bulk_actions = [] for action, data in chunk: bulk_actions.append(action) if data is not None: bulk_actions.append(data) if not bulk_actions: return def bulk(client, actions, stats_only=False, **kwargs): success, failed = 0, 0 # list of errors to be collected is not stats_only errors = [] for ok, item in streaming_bulk(client, actions, **kwargs): # go through request-reponse pairs and detect failures if not ok: if not stats_only: errors.append(item) failed += 1 else: success += 1 return success, failed if stats_only else errors
對于索引的批量刪除和更新操作,對應的文檔格式如下,更新文檔中的doc節(jié)點是必須的。
{ '_op_type': 'delete', '_index': 'index-name', '_type': 'document', '_id': 42, } { '_op_type': 'update', '_index': 'index-name', '_type': 'document', '_id': 42, 'doc': {'question': 'The life, universe and everything.'} }
常見錯誤
- SerializationError:JSON數(shù)據(jù)序列化出錯,通常是因為不支持某個節(jié)點值的數(shù)據(jù)類型
- RequestError:提交數(shù)據(jù)格式不正確
- ConflictError:索引ID沖突
- TransportError:連接無法建立
性能
上面是使用MongoDB和Elasticsearch存儲相同數(shù)據(jù)的對比,雖然服務器和操作方式都不完全相同,但可以看出數(shù)據(jù)庫對批量寫入還是比索引服務器更具備優(yōu)勢。
Elasticsearch的索引文件是自動分塊,達到千萬級數(shù)據(jù)對寫入速度也沒有影響。但在達到磁盤空間上限時,Elasticsearch出現(xiàn)了文件合并錯誤,并且大量丟失數(shù)據(jù)(共丟了100多萬條),停止客戶端寫入后,服務器也無法自動恢復,必須手動停止。在生產(chǎn)環(huán)境中這點比較致命,尤其是使用非Java客戶端,似乎無法在客戶端獲取到服務端的Java異常,這使得程序員必須很小心地處理服務端的返回信息。
相關文章
python如何調(diào)用現(xiàn)有的matlab函數(shù)
這篇文章主要介紹了python如何調(diào)用現(xiàn)有的matlab函數(shù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-12-12NumPy實現(xiàn)多維數(shù)組中的線性代數(shù)
本文主要介紹了NumPy實現(xiàn)多維數(shù)組中的線性代數(shù),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-07-07