利用mongo-connector将mongodb数据同步到elasticsearch的流程以及会遇到的坑

来源:互联网 发布:网络贷款能不能报案 编辑:程序博客网 时间:2024/05/29 03:19

原文地址
mongodb虽然也提供索引功能,但是功能比较简单,在某些场景下速度相当慢(比如模糊查询的时候)。数据量小的时候也许体现不出来,当数据量达到1000W条记录,所占硬盘大小为10G左右的时候,你就会开始为mongodb提供的查询功能感到头疼。这个时候我们一般采用一款搜索服务器作为查询的后端。我的实际需求是对存储在mongodb中的1000W条百科数据记录进行查询,一次查询包括全匹配、部分匹配等组合操作。

下面我会介绍mongodb数据同步到elasticseacrh的基本流程,以及在此过程中需要注意的一些地方,不要踩我所踩过的坑。这样,如果你的数据量和我差不多,那么至少可以给你节省10多个小时的时间。

一、mongo-connector安装及mongodb配置

这个部分比较按部就班,按照官方提供的文档来就行。本文默认读者已安装好Mongodb,Python,Elasticsearch相关软件,对应的版本分别为3.2.9,2.7.12,5.4.0,操作系统为window10。

根据你Elasticsearch版本,利用pip安装最新版本mongo-connector。(撰写本文时,Elasticsearch版本为5.X,按照mongo-connector文档说明,使用下面的命令进行安装)

pip install mongo-connector[elastic5]

命令括号中的“elastic5”表示对应的文档管理器,由这个组件来控制两个系统之间的文档如何传输。

安装好mongo-connector后,将mongodb以副本集模式进行重启。先将mongodb关闭,输入下列命令:

mongod --replSet myDevReplSet

myDexReplSet是副本集的名称,一般用rs0,这个随意。利用mongo命令进入交互界面后,使用下面的命令初始化你的服务器为副本集:

rs.initiate()

如果mongodb这部分配置出现问题,请参考其他相关文章。这一步我们已经完成所有的准备工作,接下来考虑怎么讲mongodb的数据同步到elasticsearch。

二、数据同步及建立索引

如果大家本身对elasticsearch不熟,直接照搬官网文档的命令或者一些网上的相关博客,这个部分很容易被折磨得死去活来。因此,以前没有接触过elasticsearch或者接触较少,亦或没有mongo-connector实战经验的朋友建议仔细阅读这一部分。

先把官方文档的命令搬上来:

mongo-connector -m <mongodb server hostname>:<replica set port> \                -t <replication endpoint URL, e.g. http://localhost:8983/solr> \                -d <name of doc manager, e.g., solr_doc_manager>

参数说明很详细,我也就不再啰嗦。进入官方文档对应页面“Usage with Elasticsearch”,发现我们所需要输入的命令是:

mongo-connector -m localhost:27017 -t localhost:9200 -d elastic2_doc_manager

好的,坑开始出现了。主要有三个地方需要注意。

1、首先确定你要同步哪些数据

也许你的mongodb中会有许多数据库,每个数据库中有不同的collection。先确定你要同步哪些collection。上面的命令会同步你所有的数据,如果你不指定,而mongodb中的数据又很多,估计你得等上个几天几夜了。建议你在mongodb中新建一个数据库,在该数据库下建一个表,插入几条数据进行测试。然后输入以下命令:

mongo-connector -m localhost:27017 -t localhost:9200 -d elastic2_doc_manager -n testDB.testCol

n这个option就是指定所需要同步的collection。打开浏览器,输入以下网址(默认IP及端口)来查看是否同步成功:

http://localhost:9200/_cat/indices?v

如果你在index这一列中发现了你的collection名称(测试的collection数据不要太多,几十条就可以,多刷新几次,一分钟内同步完成没问题),那么恭喜你,你的数据已经能够成功同步到elasticsearch中了,可以略过第二条,直接看第三条。如果没有,那么我们来看第二个坑。

2、确保mongo-connector连上了elasticsearch

输入mongo-connector命令后,你会发现你的终端一直保持在“Logging to XXX\XXX\mongo-connector.log”状态,因为相关的输出全是保存在这个日志文件当中的。也就是说,不打开这个文件你也不知道当前的状态是什么。假设你是直接通过elasticsearch.bat文件启动的elasticsearch,那么你能够在对应的控制台输出中看见同步的信息。

如果还是不能发现mongo-connector为何没有连上elasticsearch,有可能是elasticsearch需要认证的原因。

启动elasticsearch后,默认配置是需要输入用户名和密码进行认证。初始账号密码为elastic和changeme。如果你的mongodb数据库也有相应的账号和密码,那么命令应该改为(username是你的账号,passwd是你的密码):

mongo-connector -m username:passwd@localhost:27017 -t username:passwd@localhost:9200 -d elastic2_doc_manager -n testDB.testCol

这个时候,你再去浏览器确认,此时应该是同步成功了。

另外,在本机测试使用,如果不想使用账号密码,可以在elasticsearch的配置文件(elasticsearch.yml)中加上如下配置:

xpack.security.enabled: false

如果你安装了elasticsearch官方提供的X-PACK插件,不想每次使用Kibana可视化分析平台都输入账号和密码,那么在kibana的配置文件(kibana.yml)中也加入此配置:

xpack.security.enabled: false

重启elasticsearch和kibana,配置生效。

3、先建立索引再同步数据

首先,需要说明的是,如果直接用上述命令进行数据同步,elasticsearch会为你自动建立索引。看起来挺方便的,但是如果这些索引不符合你的查询需求,你就得删掉花了数小时甚至数十小时同步完成的索引重新配置(虽然elasticsearch支持重建索引,但是我发现重建索引的速度也相当慢。这个功能更多是用在新建索引的同时,旧的索引依然能够提供服务而不至于停机这样的场合)。

这样说可能比较抽象,举个具体的例子。我对百科数据进行查询,要求标题(Title)这个字段是完全匹配才返回结果。然而,elasticsearch默认建立的索引是对每个字进行切分,这意味着,查询的时候基本单位是字。假如我想查询“周杰伦”的相关信息,通过match对“Title”字段进行匹配,结果会返回所有“Title”字段包含“周”“杰”“伦”三个字的记录,比如“周杰伦”,“周杰伦吧”,“周杰伦星”,“周杰伦日”等。也许有的人会说,添加一个“and”操作符就好了。但此操作不能保证字符的先后顺序,比如你搜“天晴”,系统会返回“天晴”和“晴天”两类结果给你。

针对这种需求,最好的方式就是在数据同步前就建好索引和对应字段的mapping。就我的需求而言,我建立索引和mapping的代码如下(可以先安装X-PACK插件,在kibana可视化分析平台的“Dev Tools”中输入以下代码测试):

PUT /baike{  "mappings": {    "baike": {       "_all":       { "enabled":  true},       "properties": {         "Title":    { "type": "keyword"},         "Infobox":     { "type": "text", "analyzer" : "smartcn"  },         "Catalog":      { "type": "text", "analyzer" : "smartcn" },        "Category":      { "type": "text", "analyzer" : "smartcn" }      }    }  }}

“PUT”后的这个“baike”是索引的名称,对应mongodb的database名;“mapping”中的“baike”是doc_type的名称,对应mongodb的collection名。如果你想对某个字段进行全匹配,那么指定它的“type”为“keyword”,之前的版本是指定“index”为“not_analysed”,不过这个方式在新的版本中被弃用。这样一来,该字段就不会被分词处理,整个值作为整体被索引。我们就可以通过“term”来进行全匹配。如果想对某些字段进行分词处理后进行索引,那么“type”指定为“text”,“analyzer”指定为“smartcn”。smartcn是开源的中文分词系统,在elasticsearch中使用先要下载该插件。在控制台中进入elasticsearch的bin目录,输入以下命令下载插件后重启elasticsearch即可使用。

elasticsearch-plugin.bat install analysis-smartcn

用下面的代码测试“smartcn”的分词效果:

GET _analyze{  "analyzer" : "smartcn",  "text" : "四川省的省会是成都"}

结果是:

{  "tokens": [    {      "token": "四川省",      "start_offset": 0,      "end_offset": 3,      "type": "word",      "position": 0    },    {      "token": "的",      "start_offset": 3,      "end_offset": 4,      "type": "word",      "position": 1    },    {      "token": "省会",      "start_offset": 4,      "end_offset": 6,      "type": "word",      "position": 2    },    {      "token": "是",      "start_offset": 6,      "end_offset": 7,      "type": "word",      "position": 3    },    {      "token": "成都",      "start_offset": 7,      "end_offset": 9,      "type": "word",      "position": 4    }  ]}

效果对一般的应用还是够了。

输入以下代码查看对应的mapping:

GET baike/_mappings

PS. 撰写本文的时候elasticsearch的官网需要用“科学上网”的方式进行访问,下载对应的插件同样需要。如果不是走全局科学上网流量,那么控制台安装插件会失败。具体方法可以另行百科。

在做好了前面的工作后,你就可以开始用mongo-connector同步数据了。

0 0
原创粉丝点击