使用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 struct.unpack
Sep 06 Python
python通过yield实现数组全排列的方法
Mar 18 Python
Python多线程编程(一):threading模块综述
Apr 05 Python
Python 常用string函数详解
May 30 Python
TensorFlow的权值更新方法
Jun 14 Python
python制作简单五子棋游戏
Jun 18 Python
PyQT5 QTableView显示绑定数据的实例详解
Jun 25 Python
Django实现文件上传下载
Oct 06 Python
python求绝对值的三种方法小结
Dec 04 Python
Django后台管理系统的图文使用教学
Jan 20 Python
Python设计密码强度校验程序
Jul 30 Python
python urllib和urllib3知识点总结
Feb 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 常用函数库和一些实用小技巧
2009/01/01 PHP
PHP session_start()问题解疑(详细介绍)
2013/07/05 PHP
dedecms函数分享之获取某一栏目所有子栏目
2014/05/19 PHP
基于命令行执行带参数的php脚本并取得参数的方法
2016/01/25 PHP
php intval函数用法总结
2019/04/14 PHP
了解jQuery技巧来提高你的代码
2010/01/08 Javascript
删除select中所有option选项jquery代码
2013/08/12 Javascript
jQuery定义背景动态切换效果的方法
2015/03/23 Javascript
高效利用Angular中内置服务$http、$location等
2016/03/22 Javascript
JavaScript中 ES6 generator数据类型详解
2016/08/11 Javascript
js 调用百度分享功能
2017/02/27 Javascript
解决Node.js使用MySQL出现connect ECONNREFUSED 127.0.0.1:3306的问题
2017/03/09 Javascript
Angular2自定义分页组件
2017/04/19 Javascript
js点击时关闭该范围下拉菜单之外的菜单方法
2018/01/11 Javascript
Nodejs模块的调用操作实例分析
2018/12/25 NodeJs
详解python中xlrd包的安装与处理Excel表格
2016/12/16 Python
Python编程实现的图片识别功能示例
2017/08/03 Python
Pycharm设置去除显示的波浪线方法
2018/10/28 Python
python实现简单多人聊天室
2018/12/11 Python
django的ORM模型的实现原理
2019/03/04 Python
python中的Elasticsearch操作汇总
2019/10/30 Python
python flask搭建web应用教程
2019/11/19 Python
将labelme格式数据转化为标准的coco数据集格式方式
2020/02/17 Python
如何解决python多种版本冲突问题
2020/10/13 Python
Flask处理Web表单的实现方法
2021/01/31 Python
浅谈CSS3中的变形功能-transform功能
2017/12/27 HTML / CSS
美国生鲜及杂货电商:FreshDirect
2018/01/29 全球购物
英文自荐信
2013/12/15 职场文书
机械设计毕业生自荐信
2014/02/02 职场文书
2014学习优秀共产党员先进事迹思想汇报
2014/09/14 职场文书
卖车协议书范例
2014/09/16 职场文书
2014机关干部学习“焦裕禄精神”思想汇报
2014/09/19 职场文书
合作协议书范本
2014/10/25 职场文书
四风问题自查自纠工作情况报告
2014/10/28 职场文书
大雁塔导游词
2015/02/04 职场文书
工作一年自我鉴定
2019/06/20 职场文书