使用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基于mysql实现的简单队列以及跨进程锁实例详解
Jul 07 Python
在SAE上部署Python的Django框架的一些问题汇总
May 30 Python
新手如何快速入门Python(菜鸟必看篇)
Jun 10 Python
Python编写合并字典并实现敏感目录的小脚本
Feb 26 Python
python使用pygame模块实现坦克大战游戏
Mar 25 Python
如何使用pyinstaller打包32位的exe程序
May 26 Python
python操作openpyxl导出Excel 设置单元格格式及合并处理代码实例
Aug 27 Python
Python 批量刷博客园访问量脚本过程解析
Aug 30 Python
PyTorch中的Variable变量详解
Jan 07 Python
Python HTTP下载文件并显示下载进度条功能的实现
Apr 02 Python
Django CBV模型源码运行流程详解
Aug 17 Python
Python Django项目和应用的创建详解
Nov 27 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
类的另类用法--数据的封装
2006/10/09 PHP
php中__destruct与register_shutdown_function执行的先后顺序问题
2014/10/17 PHP
php计算两个坐标(经度,纬度)之间距离的方法
2015/04/17 PHP
Yii统计不同类型邮箱数量的方法
2016/10/18 PHP
一个收集图片的bookmarlet(js 刷新页面中的图片)
2010/05/27 Javascript
关闭浏览器时提示onbeforeunload事件
2013/12/25 Javascript
jQuery支持添加事件的日历特效代码分享(3种样式)
2015/08/24 Javascript
对象题目的一个坑 理解Javascript对象
2015/12/22 Javascript
jQuery 中的 DOM 操作
2016/04/26 Javascript
js 原型对象和原型链理解
2017/02/09 Javascript
图片懒加载imgLazyLoading.js使用详解
2020/09/15 Javascript
详解使用vue-cli脚手架初始化Vue项目下的项目结构
2018/03/08 Javascript
解决linux下node.js全局模块找不到的问题
2018/05/15 Javascript
微信小程序自定义tab实现多层tab嵌套功能
2018/06/15 Javascript
node+express框架中连接使用mysql(经验总结)
2018/11/10 Javascript
javascript json字符串到json对象转义问题
2019/01/22 Javascript
python梯度下降法的简单示例
2018/08/31 Python
python 实现UTC时间加减的方法
2018/12/31 Python
Python函数返回不定数量的值方法
2019/01/22 Python
使用Python 统计高频字数的方法
2019/01/31 Python
浅谈Python大神都是这样处理XML文件的
2019/05/31 Python
Pandas0.25来了千万别错过这10大好用的新功能
2019/08/07 Python
python3实现在二叉树中找出和为某一值的所有路径(推荐)
2019/12/26 Python
Python单例模式的四种创建方式实例解析
2020/03/04 Python
Python3基于print打印带颜色字符串
2020/07/06 Python
关于python tushare Tkinter构建的简单股票可视化查询系统(Beta v0.13)
2020/10/19 Python
python获取命令行参数实例方法讲解
2020/11/02 Python
详解css3中dispaly的Grid布局与Flex布局
2020/09/11 HTML / CSS
纽约的奢华内衣店:Journelle
2016/07/29 全球购物
印度领先的在线时尚商店:Koovs
2016/08/28 全球购物
《最后的姿势》教学反思
2014/02/27 职场文书
房地产财务部员工岗位职责
2014/03/12 职场文书
升职演讲稿范文
2014/05/23 职场文书
校车司机安全责任书
2015/05/11 职场文书
游戏开发中如何使用CocosCreator进行音效处理
2021/04/14 Javascript
PyTorch的Debug指南
2021/05/07 Python