【Elasticsearch】使用Python + MySQL在Elasticsearch中进行高速化【MySQL】

首先

我平常主要学习机器学习方面的知识,但在空闲时间也会接触一些与Web技术相关的内容。

这次我打算在实验室内开发一个电子图书搜索引擎,但是我对从数据库读取数据速度慢这一点感到担忧。

我本来想快速完成,所以用Python编写了一个从MySQL读取数据的服务器脚本,但是一旦数据量稍微大一些,绘图就变得很慢。

因此,我考虑引入elasticsearch以加快加载速度并解决成为瓶颈的部分。

只是简单提一下,不详细说明。

环境

    • OSX

 

    • python ver3.6.0

 

    • elasticsearch ver2.3.4

 

    • elasticsearch-jdbc ver2.3.4.1

 

    msyql

引入

假设您已经能够在 Python 中进行 MySQL 数据交互。

关于elasticsearch的介绍。
首先是elasticsearch的安装,有两种方式。

一种方法是使用brew进行操作。

使用brew安装elasticsearch

可以通过安装来实现。

另一个方法是通过官方网站https://www.elastic.co/downloads/past-releases进行下载。

本次使用公式网站下载的方法。我觉得版本可以随您的喜好选择,但如果以后需要jdbc,我认为以上环境的组合很不错。

启动

启动elasticsearch非常简单,只需要下载并解压缩文件夹,然后在bin/elasticsearch运行即可。
我建议将bin添加到路径中。

但是,只有这样很难了解elasticsearch中有什么数据,所以我们要安装一个名为elasticsearch-head的工具。

plugin install mobz/elasticsearch-head

在启动elasticsearch的情况下,可以通过http://localhost:9200/_plugin/head在浏览器中查看elasticsearch内的数据。

スクリーンショット 2017-11-23 14.18.41.png

上面的图片中的search_degital_library是我创建的索引(类似于关系型数据库中的数据表)。
现在可以开始使用elsticsearch了。

MySQL的整合

在这个elasticsearch中进行mysql数据的映射,有几种方法可供选择。

让程序处理

这一次的数据量并不是很大,所以我们就这样做了。
具体方法是使用Python从MySQL数据库中读取数据,并通过Elasticsearch的库将其插入。

使用jdbc

下载并使用用于Elasticsearch的JDBC插件,通过专门的脚本将数据导入。由于导入后索引名称会变为jdbc,且无法有效处理,因此我们放弃了这种方法。

使用logstash

如果你有兴趣,请自行调查一下。看起来使用起来很方便。

数据传输

根据这个想法,我们将把 MySQL 数据导入 Elasticsearch。

在Python中,我使用了一个名为dataset的ORM来加载MySQL数据。

pip install dataset
pip install mysqlclient

我认为多数情况下,你通过这个方法应该能够使用了。
顺便一提,我简单说明一下连接相关的内容。

import dataset

DBMS = 'mysql'
USER = '__user_name'
PASS = '__pass_word'
HOST = '__db_host'
DB   = 'search_degital_library'

db = dataset.connect('{0}://{1}:{2}@{3}/{4}?charset=utf8'.format(DBMS, USER, PASS, HOST, DB))

请将charset部分转换为适当的字符编码。

以下为批量脚本的内容。
该脚本会读取mysql数据库中的books表中的电子书id、名称、创建时间和修改时间,并通过elasticsearch库进行批量导入。

pip install elasticsearch
~~

from elasticsearch import Elasticsearch
es = Elasticsearch("localhost:9200")

# db['接続したいテーブル名']
table_books = db['books']

for data in table_books.find():
    es.index(index="search_degital_library", doc_type="books", id=data['id'], body={"name":data['name'], "created":data['created'], "modified":data['modified']})

您可以使用index方法将数据插入到Elasticsearch中。

参数是指索引名称的 index 和在 RDB 中对应表的 doc_type,在 elasticsearch 中也会创建一个名为 books 的索引。即使在 elasticsearch 中事先没有定义 index 或 doc_type,只需指定即可创建。
在 body 中使用字典类型指定列和数据。顺便提一下,在 RDB 中的列在 elasticsearch 中称为字段。

将上述内容应用于每个表中,然后流入完成。
如果数据量较大,可能最好使用工具。

使用elasticsearch-head查看时,

スクリーンショット 2017-11-23 15.13.23.png

您可以通过浏览器选项卡查看输入的数据。

接下来,我们将总结一下从Python调用Elasticsearch数据的要点。这只是最基本的用法。

使用Python访问Elasticsearch数据。

数据获取

from elasticsearch import Elasticsearch
es = Elasticsearch("localhost:9200")

单一记录

我们决定将上述图片中的一行称为记录(可能有所不同)。当要读取Elasticsearch内的一条记录时,使用get命令。

# categoriesのidが42のデータを読み込む
es.get(index="search_degital_library", doc_type="categories", id=42)
{
    '_source': 
    {
        'created': '2017-11-21T16:50:58',
        'name': 'スクレイピング', 
        'modified': '2017-11-21T16:50:58'
    }, 
    '_version': 1, 
    '_index': 'search_degital_library', 
    '_type': 'categories', 
    'found': True, 
    '_id': '42'
}

用 JSON 格式返回。使用 “get_source” 只会返回源数据部分。

获取多条记录

当需要读取多条记录时,可以使用search函数。

# categoriesのデータを全て読み込む
es.search(index="search_degital_library", doc_type="categories", body={"query": {"match_all": {}}})
{
    '_shards': 
    {
        'failed': 0, 
        'total': 5, 
        'successful': 5
    }, 
    'took': 4, 
    'hits': 
    {
        'max_score': 1.0, 
        'total': 28, 
        'hits': 
        [{
             '_type': 'categories', 
             '_source': 
             {
                 'created': '2017-11-20T15:40:10', 
                 'name': 'データ分析', 
                 'modified': '2017-11-20T15:40:10'
             }, 
             '_score': 1.0,  
             '_index': 'search_degital_library', 
             '_id': '14'
         },
          ・・・・,
         { 
             '_source': 
             {
                 'created': '2017-11-20T15:40:10', 
                 'name': '強化学習', 
                 'modified': '2017-11-20T15:40:10'
             }, 
             '_type': 'categories', 
             '_score': 1.0, 
             '_index': 'search_degital_library', 
             '_id': '10'
         }]
    }, 
    'timed_out': False
}

我原以为可以一次性加载所有内容,但默认情况下只加载了10个项目。因为search参数中有一个size选项,所以只要在那里指定,就可以获取更多的内容。

es.search(index="search_degital_library", doc_type="categories", body={"query": {"match_all": {}}, "size": 200})

因为是最大值,所以可能要设置得相对较大,或者通过某种方式获取数量并进行指定。

获得前提

指定字段并获取多个。

# nameが最適化のcategoriesのデータを読み込む
es.search(index="search_degital_library", doc_type="categories", body={"query": {"match": {"name":"最適化"}}}, "size"=100)

添加数据

我之前已经提到过,

es.index(index=インデックス名, doc_type=タイプ名, id=id_, body={"name":name_, ~})

删除数据

获取要删除记录的id。

es.delete(index=インデックス名, doc_type=タイプ名, id=id_)

如果能掌握这个,我认为基本操作就能上手了。

总结起来

当将其应用在瓶颈(特别是数据的全量提取)的部分时,原本需要5秒的绘制时间现在可以在1秒以内完成!太好了!

由于在许多地方听到过 Elasticsearch 的名字并对其产生了兴趣,所以这次有机会接触到它感到很好。

如果可以的话,请参考一下。

广告
将在 10 秒后关闭
bannerAds