使用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实现生成简单的Makefile文件代码示例
Mar 10 Python
Python编程判断这天是这一年第几天的方法示例
Apr 18 Python
Python进阶之尾递归的用法实例
Jan 31 Python
Python变量赋值的秘密分享
Apr 03 Python
解决Tensorflow使用pip安装后没有model目录的问题
Jun 13 Python
Python判断一个三位数是否为水仙花数的示例
Nov 13 Python
Python生命游戏实现原理及过程解析(附源代码)
Aug 01 Python
pyftplib中文乱码问题解决方案
Jan 11 Python
Python continue语句实例用法
Feb 06 Python
python代码xml转txt实例
Mar 10 Python
详解python环境安装selenium和手动下载安装selenium的方法
Mar 17 Python
Python Pandas解析读写 CSV 文件
Apr 11 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 array_udiff_assoc 计算两个数组的差集实例
2016/11/12 PHP
PHP二维数组实现去除重复项的方法【保留各个键值】
2017/12/21 PHP
关于laravel 日志写入失败问题汇总
2019/10/17 PHP
jscript之List Excel Color Values
2007/06/13 Javascript
仿迅雷焦点广告效果(JQuery版)
2008/11/19 Javascript
jQuery怎么解析Json字符串(Json格式/Json对象)
2013/08/09 Javascript
利用JQuery和Servlet实现跨域提交请求示例分享
2014/02/12 Javascript
js+html5实现canvas绘制简单矩形的方法
2015/06/05 Javascript
深入理解JavaScript的React框架的原理
2015/07/02 Javascript
解决JS无法调用Controller问题的方法
2015/12/31 Javascript
jQuery中通过ajax的get()函数读取页面的方法
2016/02/29 Javascript
JavaScript原生编写《飞机大战坦克》游戏完整实例
2017/01/04 Javascript
JavaScript调试的多个必备小Tips
2017/01/15 Javascript
微信小程序商城项目之购物数量加减(3)
2017/04/17 Javascript
微信小程序 侧滑删除(左滑删除)
2017/05/23 Javascript
vue弹窗插件实战代码
2018/09/08 Javascript
解决layui数据表格排序图标被超出的表头挤出去的问题
2019/09/19 Javascript
浅谈vue项目,访问路径#号的问题
2020/08/14 Javascript
详解实现vue的数据响应式原理
2021/01/20 Vue.js
Python初学时购物车程序练习实例(推荐)
2017/08/08 Python
Python3.5.3下配置opencv3.2.0的操作方法
2018/04/02 Python
python3读取excel文件只提取某些行某些列的值方法
2018/07/10 Python
详解Python中的type和object
2018/08/15 Python
在pandas多重索引multiIndex中选定指定索引的行方法
2018/11/16 Python
把pandas转换int型为str型的方法
2019/01/29 Python
Python 实现数据结构中的的栈队列
2019/05/16 Python
django 环境变量配置过程详解
2019/08/06 Python
Django实现auth模块下的登录注册与注销功能
2019/10/10 Python
从pandas一个单元格的字符串中提取字符串方式
2019/12/17 Python
加拿大时尚潮流大码女装购物网站:Addition Elle
2018/04/02 全球购物
英国Radley包德国官网:Radley London德国
2019/11/18 全球购物
保险专业大专生求职信
2013/10/26 职场文书
爱情检讨书大全
2014/01/21 职场文书
简单的辞职信怎么写
2015/02/28 职场文书
django学习之ajax post传参的2种格式实例
2021/05/14 Python
PHP面试题 wakeup魔法 Ezpop pop序列化与反序列化
2022/04/11 PHP