使用Elasticsearch实现对MySQL(MariaDB)数据的全文检索

虽然如此,不直接使用MySQL进行全文搜索,而是将MySQL数据导入到Elasticsearch,并在Elasticsearch中进行全文搜索。使用的操作系统是CentOS7。

最开始

    • Elasticsearchは各種プラグインなどマイナーバージョンの組み合わせでもかなりシビアです。トラブル回避のためにも、すべてのバージョンは完全に合わせましょう。

 

    この投稿も将来的に動かない可能性もあります。その際は、最新版のドキュメントを。私は適当にググってバージョン違いでハマったので…。

巨大的洪流

    1. 准备

 

    1. 安装Elasticsearch 1.7.1(最新版于2015/08/19发布)

 

    1. 安装和设置Elasticsearch的插件

 

    1. 准备数据在MariaDB上

 

    1. 配置jdbc连接

 

    在MariaDB上修改数据

这次不会组集群。全部都会用一台机器来做。

做好准备

以下是CentOS7。
由于elasticsearch需要Java,因此需要安装Java。此外,可以使用以下指令安装jdk1.8。

# yum install java curl wget unzip

安装最新版的Elasticsearch 1.7.1(2015/08/19)

添加仓库。请注意版本指定。

# vi /etc/yum.repos.d/elasticsearch.repo
-----
[elasticsearch-1.7]
name=Elasticsearch repository for 1.7.x packages
baseurl=http://packages.elastic.co/elasticsearch/1.7/centos
gpgcheck=1
gpgkey=http://packages.elastic.co/GPG-KEY-elasticsearch
enabled=1
-----
# yum install elasticsearch

顺便提一下,elasticsearch会安装在/usr/share/elasticsearch目录下。

3. 安装和配置Elasticsearch的插件

各种插件 (gè

确认应安装的kuromoji版本,请查看这里。版本应严格对应。链接:https://github.com/elastic/elasticsearch-analysis-kuromoji

# /usr/share/elasticsearch/bin/plugin -install elasticsearch/elasticsearch-analysis-kuromoji/2.7.0
# /usr/share/elasticsearch/bin/plugin -install mobz/elasticsearch-head

Elasticsearch的启动和自动启动设置

# systemctl start elasticsearch.service
# systemctl enable elasticsearch.service
# systemctl daemon-reload

对Elasticsearch进行运行验证

# curl http://localhost:9200

确认能够通过网络浏览器从外部访问。

(※IP地址为192.168.0.33,请注意selinux和firewalld)
http://192.168.0.33:9200/_plugin/head/

确认Elasticsearch的插件。

# curl -XGET 'http://localhost:9200/_nodes?plugin=true&pretty'
   :
      "plugins" : [ {
        "name" : "analysis-kuromoji",
        "version" : "2.7.0",
        "description" : "Kuromoji analysis support",
        "jvm" : true,
        "site" : false
      }, {
        "name" : "head",
        "version" : "NA",
        "description" : "No description found.",
        "url" : "/_plugin/head/",
        "jvm" : false,
        "site" : true
      } ]
  :

查看Elasticsearch的日志

希望没有发生任何错误…。

# less /var/log/elasticsearch/elasticsearch.log

将kuromoji设置为默认的分词器。

# vi /etc/elasticsearch/elasticsearch.yml
-----
index.analysis.analyzer.default.type: custom
index.analysis.analyzer.default.tokenizer: kuromoji_tokenizer
-----
# systemctl restart elasticsearch.service

4. 在MariaDB中准备数据。

与MariaDB的合作

现在,我们已经准备就绪。终于轮到MariaDB(MySQL)的协作了。然而,在开始之前,我们需要准备原始数据。如果您已经有示例数据,那么您可以跳过下一步。请准备好select语句。

准备数据

我将使用全国邮政编码数据。大约有12万条数据。因此,我写了一个将全国邮政编码数据最快速地存入MySQL(MariaDB)的方法。

在使用JDBC协议进行连接之前

参考にし、必要なバージョンをダウンロードする必要がありますが、これはelasticsearch本体と厳密に一致させる必要があり、私はハマってしまいました。
かつてはriverプラグインとして提供されていたかもしれませんが、これにもハマることがあります。検索すると情報が錯綜しています。
このjdbc連携はプラグインではなく、単独のツールとして提供されているようです。

5. JDBC协议连接

下載用於 Elasticsearch 1.7.1 的 JDBC 連接工具。

现在是2015年8月19日,使用wget命令下载。

# wget http://xbib.org/repository/org/xbib/elasticsearch/importer/elasticsearch-jdbc/1.7.1.0/elasticsearch-jdbc-1.7.1.0-dist.zip
# unzip elasticsearch-jdbc-1.7.1.0-dist.zip
# cd elasticsearch-jdbc-1.7.1.0/
# ls lib

在ls命令下,我们能确认mysql-connector-java-5.1.33.jar文件是否已经存在。
所以,不需要单独下载它。

创建JDBC链接脚本(同步脚本)。

# cd bin/
# pwd 
/root/elasticsearch-jdbc-1.7.1.0/bin
# ls

有许多不同的脚本可供选择,但我将选择最简单却有点凶恶的“mysql-delete-document.sh”作为基础。

# cp mysql-delete-document.sh mysql-oreore.sh
# vi mysql-oreore.sh
-----
    "jdbc" : {
        "url" : "jdbc:mysql://localhost:3306/sampledb",
        "user" : "root",
        "password" : "",
        "sql" :  "select id as _id, jiscode, zipcode_old, zipcode, pref_kana, city_kana, street_kana, pref, city, street from zipcode"
    }
-----

我将编辑mysql的连接配置和sql。然后,在jdbc部分,它变成了上面的样子。
这个sql是用来将全国邮政编码数据尽快放入MySQL(MariaDB)的。
重要的地方是,在select语句中的’id as _id’,将_id指定为唯一的id。

执行同步脚本

现在,一切准备就绪,我们开始执行从MySQL到Elasticsearch的数据导入。请运行下面的同步脚本,并稍等片刻。

# ./mysql-oreore.sh

在Elasticsearch中执行搜索

# curl -XGET 'http://localhost:9200/jdbc/_search?pretty=true' -d '
{
  "query": {
    "match": {
      "street": "鈴木"
    }
  }
}
'

搜索结果共有3条。

 :
  "hits" : {
    "total" : 3,
    "max_score" : 10.423999,
    "hits" : [ {
      "_index" : "jdbc",
      "_type" : "jdbc",
      "_id" : "26915",
      "_score" : 10.423999,
      "_source":{"jiscode":"08443","zipcode_old":"30003","zipcode":"3000334","pref_kana":"イバラキケン","city_kana":"イナシキグンアミマチ","street_kana":"スズキ","pref":"茨城県","city":"稲敷郡阿見町","street":"鈴木"}
    }, {
      "_index" : "jdbc",
      "_type" : "jdbc",
      "_id" : "41720",
      "_score" : 6.5149994,
      "_source":{"jiscode":"14131","zipcode_old":"210  ","zipcode":"2100801","pref_kana":"カナガワケン","city_kana":"カワサキシカワサキク","street_kana":"スズキチョウ","pref":"神奈川県","city":"川崎市川崎区","street":"鈴木町"}
    }, {
      "_index" : "jdbc",
      "_type" : "jdbc",
      "_id" : "40372",
      "_score" : 6.514974,
      "_source":{"jiscode":"13211","zipcode_old":"187  ","zipcode":"1870011","pref_kana":"トウキョウト","city_kana":"コダイラシ","street_kana":"スズキチョウ","pref":"東京都","city":"小平市","street":"鈴木町"}
    } ]
  }
 :

无事搜索到了。太棒了。

6. 在MariaDB中进行数据更改。

现在,邮政编码并不是每天都会改变,但实际上它们确实会相当频繁地变化。
如果数据发生了更改,那会怎样呢?

MariaDB数据的修改

我会在更新文件中进行修改。

# mysql sampledb
MariaDB [sampledb]> select * from zipcode where id = 26915 \G
MariaDB [sampledb]> update zipcode set street = '鈴木さん' where id = 26915;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
MariaDB [sampledb]> \q

我将使用刚才的命令再次查询一次,但显然结果相同。
因此,我将再次运行同步程序。

# ./mysql-oreore.sh

重新搜索。

# curl -XGET 'http://localhost:9200/jdbc/_search?pretty=true' -d '
{
  "query": {
    "match": {
      "street": "鈴木"
    }
  }
}
'

然后,…

{
 :
  "hits" : {
    "total" : 3,
    "max_score" : 6.5149994,
    "hits" : [ {
      "_index" : "jdbc",
      "_type" : "jdbc",
      "_id" : "26915",
      "_score" : 6.5149994,
      "_source":{"jiscode":"08443","zipcode_old":"30003","zipcode":"3000334","pref_kana":"イバラキケン","city_kana":"イナシキグンアミマチ","street_kana":"スズキ","pref":"茨城県","city":"稲敷郡阿見町","street":"鈴木さん"}
    }, {
      "_index" : "jdbc",
      "_type" : "jdbc",
      "_id" : "41720",
      "_score" : 6.5149994,
      "_source":{"jiscode":"14131","zipcode_old":"210  ","zipcode":"2100801","pref_kana":"カナガワケン","city_kana":"カワサキシカワサキク","street_kana":"スズキチョウ","pref":"神奈川県","city":"川崎市川崎区","street":"鈴木町"}
    }, {
      "_index" : "jdbc",
      "_type" : "jdbc",
      "_id" : "40372",
      "_score" : 6.514974,
      "_source":{"jiscode":"13211","zipcode_old":"187  ","zipcode":"1870011","pref_kana":"トウキョウト","city_kana":"コダイラシ","street_kana":"スズキチョウ","pref":"東京都","city":"小平市","street":"鈴木町"}
    } ]
  }
 :

哇,第一条数据从“鈴木”成功变更为“鈴木さん”!

‘_id’是重要的,如果没有指定,系统会自动分配_id,并且在运行jdbc同步脚本时每次都会添加,导致重复数据的产生。

7. 总结

我用一种最简单的方法试着做了一遍,直到它动起来。

即使有复杂的表结构,只要修改select语句,就可以进行各种搜索,并且可以使用crontab定期运行同步脚本,在数据量不多且变化不大的情况下,大约几万条数据,这样就可以了。

实际上,在Elasticsearch中需要进行模式设置和集群配置。

另外,如果查看bin目录中与schedule相关的脚本,比如https://github.com/jprante/elasticsearch-jdbc,似乎可以更高效地运行。请注意,此次操作涉及全量获取,因此会稍微占用一些资源。

最好不要在Elasticsearch中进行搜索并捕获ID,然后在MySQL中通过IN进行筛选。最好将所有与展示无关但是必要的数据一起带到Elasticsearch,并仅通过Elasticsearch的搜索结果创建画面。但是,请注意对于对时间延迟要求敏感的需求需要小心处理时间延迟。

如果要重新进行全部操作,请删除索引。

# curl -XDELETE 'http://localhost:9200/jdbc'
广告
将在 10 秒后关闭
bannerAds