使用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使用socket远程连接错误处理方法
Apr 29 Python
Python简单网络编程示例【客户端与服务端】
May 26 Python
django静态文件加载的方法
May 20 Python
详解windows python3.7安装numpy问题的解决方法
Aug 13 Python
python redis 删除key脚本的实例
Feb 19 Python
Python使用paramiko操作linux的方法讲解
Feb 25 Python
Python面向对象进阶学习
May 21 Python
解决python 读取 log日志的编码问题
Dec 24 Python
python实现简单井字棋游戏
Mar 04 Python
在echarts中图例legend和坐标系grid实现左右布局实例
May 16 Python
python 19个值得学习的编程技巧
Aug 15 Python
Python配置pip国内镜像源的实现
Aug 20 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中获取变量的变量名的一段代码的bug分析
2011/07/07 PHP
Php header()函数语法及使用代码
2013/11/04 PHP
PHP生成随机字符串(3种方法)
2015/09/25 PHP
PHP使用Redis长连接的方法详解
2018/02/12 PHP
PHP 计算两个特别大的整数实例代码
2018/05/07 PHP
php字符串函数 str类常见用法示例
2020/05/15 PHP
Ext JS 4实现带week(星期)的日期选择控件(实战一)
2013/08/21 Javascript
一个JavaScript函数把URL参数解析成Json对象
2014/09/24 Javascript
JS 获取鼠标左右键的键值方法
2014/10/11 Javascript
jQuery中:first-child选择器用法实例
2014/12/31 Javascript
使用jQuery监听DOM元素大小变化
2016/02/24 Javascript
JavaScript入门系列之知识点总结
2016/03/24 Javascript
JavaScript实现鼠标点击导航栏变色特效
2017/02/08 Javascript
jquery与js实现全选功能的区别
2017/06/11 jQuery
vue.js中v-on:textInput无法执行事件问题的解决过程
2017/07/12 Javascript
Node.js 基础教程之全局对象
2017/08/06 Javascript
js推箱子小游戏步骤代码解析
2018/01/10 Javascript
Vue+axios实现统一接口管理的方法
2018/07/23 Javascript
原生JS+HTML5实现的可调节写字板功能示例
2018/08/30 Javascript
微信小程序实现带缩略图轮播效果
2018/11/04 Javascript
JavaScript之实现一个简单的Vue示例
2019/01/17 Javascript
js实现弹出框的拖拽效果实例代码详解
2019/04/16 Javascript
layer.open组件获取弹出层页面变量、函数的实例
2019/09/25 Javascript
Vue.js页面中有多个input搜索框如何实现防抖操作
2019/11/04 Javascript
js实现鼠标滑动到某个div禁止滚动
2020/09/17 Javascript
python生成随机验证码(中文验证码)示例
2014/04/03 Python
Python操作MySQL简单实现方法
2015/01/26 Python
使用Python脚本来获取Cisco设备信息的示例
2015/05/04 Python
python腾讯语音合成实现过程解析
2019/08/01 Python
python 如何把docker-compose.yaml导入到数据库相关条目里
2021/01/15 Python
50个强大璀璨的CSS3/JS技术运用实例
2010/02/27 HTML / CSS
MyBag中文网:英国著名的时尚包袋电商零售网站
2020/07/31 全球购物
土木工程个人自荐信范文
2013/11/30 职场文书
2014年禁毒工作总结
2014/11/24 职场文书
颐和园的导游词
2015/01/30 职场文书
SQL基础查询和LINQ集成化查询
2022/01/18 MySQL