使用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中处理时间的几种方法小结
Apr 09 Python
Python入门之后再看点什么好?
Mar 05 Python
pycharm运行出现ImportError:No module named的解决方法
Oct 13 Python
Python 支付整合开发包的实现
Jan 23 Python
用uWSGI和Nginx部署Flask项目的方法示例
May 05 Python
深入了解Django View(视图系统)
Jul 23 Python
Python flask框架如何显示图像到web页面
Jun 03 Python
Scrapy框架介绍之Puppeteer渲染的使用
Jun 19 Python
使用 prometheus python 库编写自定义指标的方法(完整代码)
Jun 29 Python
python zip()函数的使用示例
Sep 23 Python
Python模拟登录requests.Session应用详解
Nov 17 Python
Python 详解通过Scrapy框架实现爬取CSDN全站热榜标题热词流程
Nov 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下intval()和(int)转换使用与区别
2008/07/18 PHP
PHP运行时强制显示出错信息的代码
2011/04/20 PHP
win7计划任务定时执行PHP脚本设置图解
2014/05/09 PHP
PHP生成json和xml类型接口数据格式
2015/05/17 PHP
php根据用户名和手机号查询是否存在手机号码
2017/02/16 PHP
如何使用jQuery Draggable和Droppable实现拖拽功能
2013/07/05 Javascript
JS实现div居中示例
2014/04/17 Javascript
jQuery实现带滑动条的菜单效果代码
2015/08/26 Javascript
node.js抓取并分析网页内容有无特殊内容的js文件
2015/11/17 Javascript
jquery实现全屏滚动
2015/12/28 Javascript
JavaScript如何实现组合列表框中元素移动效果
2016/03/01 Javascript
浅析JavaScript中浏览器的兼容问题
2016/04/19 Javascript
微信小程序 视图层(xx.xml)和逻辑层(xx.js)详细介绍
2016/10/13 Javascript
浅析javascript中的Event事件
2016/12/09 Javascript
js删除数组中的元素delete和splice的区别详解
2018/02/03 Javascript
浅谈Node 调试工具入门教程
2018/03/20 Javascript
el-input 标签中密码的显示和隐藏功能的实例代码
2019/07/19 Javascript
vue中 v-for循环的用法详解
2020/02/19 Javascript
[00:37]2016完美“圣”典风云人物:rOtk宣传片
2016/12/09 DOTA
python访问sqlserver示例
2014/02/10 Python
Python fileinput模块使用实例
2015/05/28 Python
python魔法方法-属性转换和类的表示详解
2016/07/22 Python
基于python实现KNN分类算法
2020/04/23 Python
Python实现html转换为pdf报告(生成pdf报告)功能示例
2019/05/04 Python
PyTorch的深度学习入门之PyTorch安装和配置
2019/06/27 Python
如何爬取通过ajax加载数据的网站
2019/08/15 Python
Python 脚本实现淘宝准点秒杀功能
2019/11/13 Python
五分钟带你搞懂python 迭代器与生成器
2020/08/30 Python
matplotlib对象拾取事件处理的实现
2021/01/14 Python
详解如何使用rem或viewport进行移动端适配
2020/08/14 HTML / CSS
努比亚手机官网:nubia
2016/10/06 全球购物
大学生职业规划前言模板
2013/12/27 职场文书
生死抉择观后感
2015/06/09 职场文书
导游词之山东红叶谷
2019/10/31 职场文书
CSS3 天气图标动画效果
2021/04/06 HTML / CSS
Python爬虫基础讲解之请求
2021/05/13 Python