使用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 logging类库使用例子
Nov 22 Python
Python中进程和线程的区别详解
Oct 29 Python
Python2.X/Python3.X中urllib库区别讲解
Dec 19 Python
python实现图片批量压缩程序
Jul 23 Python
详解Python 定时框架 Apscheduler原理及安装过程
Jun 14 Python
python3光学字符识别模块tesserocr与pytesseract的使用详解
Feb 26 Python
python实现字符串和数字拼接
Mar 02 Python
jupyter notebook实现显示行号
Apr 13 Python
解决keras模型保存h5文件提示无此目录问题
Jul 01 Python
详解python定时简单爬取网页新闻存入数据库并发送邮件
Nov 27 Python
python接口测试返回数据为字典取值方式
Feb 12 Python
Python+Matplotlib+LaTeX玩转数学公式
Feb 24 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
yii2.0整合阿里云oss上传单个文件的示例
2017/09/19 PHP
理解Javascript_11_constructor实现原理
2010/10/18 Javascript
JQuery中$之选择器用法介绍
2011/04/05 Javascript
js自定义事件及事件交互原理概述(二)
2013/02/01 Javascript
js获得指定控件输入光标的坐标兼容IE,Chrome,火狐等多种主流浏览器
2013/05/21 Javascript
node.js中的buffer.Buffer.isBuffer方法使用说明
2014/12/14 Javascript
浅谈javascript中的instanceof和typeof
2015/02/27 Javascript
js的flv视频播放器插件使用方法
2015/06/23 Javascript
JS控制表单提交的方法
2015/07/09 Javascript
Vue.js Ajax动态参数与列表显示实现方法
2016/10/20 Javascript
有趣的bootstrap走动进度条
2016/12/01 Javascript
JS中SetTimeout和SetInterval使用初探
2017/03/23 Javascript
vue resource post请求时遇到的坑
2017/10/19 Javascript
vue2+el-menu实现路由跳转及当前项的设置方法实例
2017/11/07 Javascript
jQuery实现的导航条点击后高亮显示功能示例
2019/03/04 jQuery
[49:31]TFT vs Mski Supermajor小组赛C组 BO3 第一场 6.3
2018/06/04 DOTA
python操作redis的方法
2015/07/07 Python
使用pygame模块编写贪吃蛇的实例讲解
2018/02/05 Python
详解Python使用tensorflow入门指南
2018/02/09 Python
Python实现批量修改图片格式和大小的方法【opencv库与PIL库】
2018/12/03 Python
python中ImageTk.PhotoImage()不显示图片却不报错问题解决
2018/12/06 Python
django模板加载静态文件的方法步骤
2019/03/01 Python
Python实现的微信支付方式总结【三种方式】
2019/04/13 Python
python实现日志按天分割
2019/07/22 Python
工商学院毕业生个人自我评价
2013/09/19 职场文书
大学生优秀团员事迹材料
2014/01/30 职场文书
春节联欢会主持词
2014/03/24 职场文书
一年级评语大全
2014/04/23 职场文书
个人工作作风整改措施思想汇报
2014/10/13 职场文书
2015新年寄语(一句话)
2014/12/08 职场文书
教师先进个人材料
2014/12/17 职场文书
申报材料格式
2014/12/30 职场文书
歌舞青春观后感
2015/06/10 职场文书
Python带你从浅入深探究Tuple(基础篇)
2021/05/15 Python
springcloud之Feign超时问题的解决
2021/06/24 Java/Android
基于Python实现对比Exce的工具
2022/04/07 Python