使用Python操作Elasticsearch数据索引的教程

作者:陈加兴 时间:2021-03-04 22:51:28 

Elasticsearch是一个分布式、Restful的搜索及分析服务器,Apache Solr一样,它也是基于Lucence的索引服务器,但我认为Elasticsearch对比Solr的优点在于:

  •     轻量级:安装启动方便,下载文件之后一条命令就可以启动;

  •     Schema free:可以向服务器提交任意结构的JSON对象,Solr中使用schema.xml指定了索引结构;

  •     多索引文件支持:使用不同的index参数就能创建另一个索引文件,Solr中需要另行配置;

  •     分布式:Solr Cloud的配置比较复杂。

环境搭建

启动Elasticsearch,访问端口在9200,通过浏览器可以查看到返回的JSON数据,Elasticsearch提交和返回的数据格式都是JSON.


>> bin/elasticsearch -f

安装官方提供的Python API,在OS X上安装后出现一些Python运行错误,是因为setuptools版本太旧引起的,删除重装后恢复正常。


>> pip install elasticsearch

索引操作

对于单条索引,可以调用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)]

在这里发现Python API序列化JSON时对数据类型支撑比较有限,原始数据使用的NumPy.Int32必须转换为int才能索引。此外,现在的bulk操作默认是每次提交500条数据,我修改为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节点是必须的。


{
 '_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数据序列化出错,通常是因为不支持某个节点值的数据类型

  •     RequestError:提交数据格式不正确

  •     ConflictError:索引ID冲突

  •     TransportError:连接无法建立

性能

使用Python操作Elasticsearch数据索引的教程

上面是使用MongoDB和Elasticsearch存储相同数据的对比,虽然服务器和操作方式都不完全相同,但可以看出数据库对批量写入还是比索引服务器更具备优势。

Elasticsearch的索引文件是自动分块,达到千万级数据对写入速度也没有影响。但在达到磁盘空间上限时,Elasticsearch出现了文件合并错误,并且大量丢失数据(共丢了100多万条),停止客户端写入后,服务器也无法自动恢复,必须手动停止。在生产环境中这点比较致命,尤其是使用非Java客户端,似乎无法在客户端获取到服务端的Java异常,这使得程序员必须很小心地处理服务端的返回信息。

标签:Python,数据库
0
投稿

猜你喜欢

  • Python栈的实现方法示例【列表、单链表】

    2023-07-20 15:51:42
  • Django配置MySQL数据库的完整步骤

    2023-07-19 14:43:47
  • Python的组合模式与责任链模式编程示例

    2023-05-08 07:03:43
  • Python SMTP发送电子邮件的示例

    2023-09-26 17:57:24
  • 纯手工打造CSS像素画

    2009-03-09 12:57:00
  • python进行两个表格对比的方法

    2021-12-15 20:31:57
  • 两种与SQL Server数据库交换数据的方法

    2008-12-10 15:39:00
  • Django项目如何给数据库添加约束

    2023-08-10 14:49:39
  • Python数据分析之获取双色球历史信息的方法示例

    2022-10-05 21:16:34
  • SQL Server命令行导数据的2种方式

    2010-07-26 14:48:00
  • JSP 开发之 releaseSession的实例详解

    2023-06-14 11:49:03
  • 如何尽快释放掉Connection对象建立的连接?

    2009-12-16 18:38:00
  • Python+pandas编写命令行脚本操作excel的tips详情

    2023-09-23 22:35:53
  • Django中使用haystack+whoosh实现搜索功能

    2021-10-12 23:54:14
  • centos6.7安装python2.7.11的具体方法

    2022-04-29 00:42:54
  • 无刷新dropdownlist并进行关联(js+xml)

    2007-09-23 12:13:00
  • python简单程序读取串口信息的方法

    2024-01-02 02:42:18
  • python 爬取百度文库并下载(免费文章限定)

    2022-05-08 16:18:28
  • Python实现按逗号分隔列表的方法

    2023-06-08 08:32:16
  • 用Python在Excel里画出蒙娜丽莎的方法示例

    2023-12-18 02:59:21
  • asp之家 网络编程 m.aspxhome.com