使用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使用cookie库操保存cookie详解
Mar 03 Python
用python代码做configure文件
Jul 20 Python
python入门之语句(if语句、while语句、for语句)
Jan 19 Python
使用Python的Twisted框架构建非阻塞下载程序的实例教程
May 25 Python
python爬虫之BeautifulSoup 使用select方法详解
Oct 23 Python
Caffe均值文件mean.binaryproto转mean.npy的方法
Jul 09 Python
转换科学计数法的数值字符串为decimal类型的方法
Jul 16 Python
pandas删除行删除列增加行增加列的实现
Jul 06 Python
HTML的form表单和django的form表单
Jul 25 Python
对python中的装包与解包实例详解
Aug 24 Python
Python 内置函数globals()和locals()对比详解
Dec 23 Python
TensorFlow2.X结合OpenCV 实现手势识别功能
Apr 08 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
创建数据库php代码 用PHP写出自己的BLOG系统
2010/04/12 PHP
PHP防止跨域提交表单
2013/11/01 PHP
php修改文件上传限制方法汇总
2015/04/07 PHP
yii2整合百度编辑器umeditor及umeditor图片上传问题的解决办法
2016/04/20 PHP
PHP加密解密类实例代码
2016/07/20 PHP
PHP PDOStatement::setFetchMode讲解
2019/02/03 PHP
PHP7生产环境队列Beanstalkd用法详解
2020/05/19 PHP
use jscript Create a SQL Server database
2007/06/16 Javascript
Javascript this关键字使用分析
2008/10/21 Javascript
精心挑选的15款优秀jQuery 本特效插件和教程
2012/08/06 Javascript
使用Java实现简单的server/client回显功能的方法介绍
2013/05/03 Javascript
使用非html5实现js板连连看游戏示例代码
2013/09/22 Javascript
jquery通过a标签删除table中的一行的代码
2013/12/02 Javascript
JS动态调用方法名示例介绍
2013/12/18 Javascript
jQuery使用中可能被XSS攻击的一些危险环节提醒
2016/05/24 Javascript
JavaScript限制在客户区可见范围的拖拽(解决scrollLeft和scrollTop的问题)(2)
2017/05/17 Javascript
聊聊那些使用前端Javascript实现的机器学习类库
2017/09/18 Javascript
vue地区选择组件教程详解
2018/05/04 Javascript
[09:37]2018DOTA2国际邀请赛寻真——不懈追梦的Team Serenity
2018/08/13 DOTA
Python heapq使用详解及实例代码
2017/01/25 Python
对Python 文件夹遍历和文件查找的实例讲解
2018/04/26 Python
基于python的列表list和集合set操作
2019/11/24 Python
Python 内置函数globals()和locals()对比详解
2019/12/23 Python
Python中用pyinstaller打包时的图标问题及解决方法
2020/02/17 Python
Pyecharts 动态地图 geo()和map()的安装与用法详解
2020/03/25 Python
Pytorch生成随机数Tensor的方法汇总
2020/09/09 Python
canvas实现扭蛋机动画效果的示例代码
2018/10/17 HTML / CSS
LivingSocial英国:英国本地优惠
2019/02/22 全球购物
Shopbop中文官网:美国亚马逊旗下时尚购物网站
2020/12/15 全球购物
医院总经理职责
2013/12/26 职场文书
五年级科学教学反思
2014/02/05 职场文书
老总助理工作岗位职责
2014/02/06 职场文书
物控部经理职务说明书
2014/02/25 职场文书
2015年党建工作目标责任书
2015/05/08 职场文书
毕业论文致谢部分怎么写
2015/05/14 职场文书
银行安全保卫工作总结
2015/08/10 职场文书