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


Posted in Python onApril 08, 2015

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 相关文章推荐
Python读取MRI并显示为灰度图像实例代码
Jan 03 Python
Python贪心算法实例小结
Apr 22 Python
pandas 空的dataframe 插入列名的示例
Oct 30 Python
python调用matlab的m自定义函数方法
Feb 18 Python
对python中不同模块(函数、类、变量)的调用详解
Jul 16 Python
全面了解django的缓存机制及使用方法
Jul 22 Python
python 实现绘制整齐的表格
Nov 18 Python
python中的split()函数和os.path.split()函数使用详解
Dec 21 Python
PYQT5 vscode联合操作qtdesigner的方法
Mar 24 Python
python 两种方法修改文件的创建时间、修改时间、访问时间
Sep 26 Python
pytest fixtures装饰器的使用和如何控制用例的执行顺序
Jan 28 Python
C站最全Python标准库总结,你想要的都在这里
Jul 03 Python
用Python实现协同过滤的教程
Apr 08 #Python
在Python中调用ggplot的三种方法
Apr 08 #Python
Python字符串和文件操作常用函数分析
Apr 08 #Python
Python遍历zip文件输出名称时出现乱码问题的解决方法
Apr 08 #Python
python smtplib模块发送SSL/TLS安全邮件实例
Apr 08 #Python
python复制与引用用法分析
Apr 08 #Python
Python导入txt数据到mysql的方法
Apr 08 #Python
You might like
用C/C++扩展你的PHP 为你的php增加功能
2012/09/06 PHP
php利用反射实现插件机制的方法
2015/03/14 PHP
php die()与exit()的区别实例详解
2016/12/03 PHP
PHP 网站修改默认访问文件的nginx配置
2017/05/27 PHP
PHP实现广度优先搜索算法(BFS,Broad First Search)详解
2017/09/16 PHP
PHP异步进程助手async-helper
2018/02/05 PHP
慎用 somefunction.prototype 分析
2009/06/02 Javascript
javascript 匿名函数的理解(透彻版)
2010/01/28 Javascript
JavaScript CSS修改学习第三章 修改样式表
2010/02/19 Javascript
基于jquery实现的可以编辑选择的下拉框的代码
2010/11/19 Javascript
JavaScript的parseInt 取整使用
2011/05/09 Javascript
如何解决ligerUI布局时Center中的Tab高度大小
2015/11/24 Javascript
JavaScript动态生成二维码图片
2016/04/20 Javascript
React-Native实现ListView组件之上拉刷新实例(iOS和Android通用)
2017/07/11 Javascript
easyui下拉框动态级联加载的示例代码
2017/11/29 Javascript
JS动态插入脚本和插入引用外部链接脚本的方法
2018/05/21 Javascript
vue-cli3全面配置详解
2018/11/14 Javascript
微信小程序如何实现radio单选框单击打勾和取消
2020/01/21 Javascript
JS使用setInterval计时器实现挑战10秒
2020/11/08 Javascript
jquery实现拖拽添加元素功能
2020/12/01 jQuery
理解python多线程(python多线程简明教程)
2014/06/09 Python
transform python环境快速配置方法
2018/09/27 Python
Python判断是否json是否包含一个key的方法
2018/12/31 Python
python pandas写入excel文件的方法示例
2019/06/25 Python
python 制作网站筛选工具(附源码)
2021/01/21 Python
Tiqets荷兰:出售欧洲最美丽的景点和博物馆门票
2018/01/09 全球购物
德国最大的网上足球商店:11teamsports
2019/09/11 全球购物
什么是Connection-oriented Protocol/Connectionless Protocol面向连接的协议/无连接协议
2012/09/06 面试题
村官工作鉴定评语
2014/01/27 职场文书
体育专业自荐书
2014/05/29 职场文书
机械设备与数控技术专业求职信
2014/08/10 职场文书
党员干部群众路线个人整改措施
2014/09/18 职场文书
学习雷锋精神倡议书
2015/04/27 职场文书
初一英语教学反思
2016/02/15 职场文书
导游词之海南-南湾猴岛
2019/10/12 职场文书
sql server偶发出现死锁的解决方法
2022/04/10 SQL Server