Elasticsearch,为了搜索
Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。
但是,Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。
Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单。
如果没有搜索引擎,单单凭借Mysql提供的简单搜索功能,无论在性能还是效果上都不尽如人意,继承程序猿的折腾属性,决定将自己的博客插上Elasticsearch的翅膀。
安装 Oracle JDK
sudo apt-get update
sudo apt-get install openjdk-8-jdk
安装 Elasticsearch
-
下载
wget https://download.elasticsearch.org/elasticsearch/elasticsearch/elasticsearch-2.3.4.deb sudo dpkg -i elasticsearch-2.3.4.deb
目前ElasticSearch的中文分词插件IK最高版本为1.9.4,兼容Elasticsearch的2.3.4版本。
-
安装
sudo dpkg -i elasticsearch-2.3.4.deb
-
开机自启动
sudo update-rc.d elasticsearch defaults 95 10 sudo service elasticsearch start
-
测试
curl http://localhost:9200
你如果你看到以下信息,说明你的ElasticSearch已安装成功。
{
"name" : "Peter Petruski",
"cluster_name" : "elasticsearch",
"version" : {
"number" : "2.3.4",
"build_hash" : "...(隐藏)",
"build_timestamp" : "2016-06-30T11:24:31Z",
"build_snapshot" : false,
"lucene_version" : "5.5.0"
},
"tagline" : "You Know, for Search"
}
默认情况下 Elasticsearch 的 RESTful 服务只有本机才能访问,也就是说无法从主机访问虚拟机中的服务。为了方便调试,可以修改 /etc/elasticsearch/config/elasticsearch.yml
文件,加入以下两行:
network.bind_host: “0.0.0.0"
network.publish_host: \_non_loopback:ipv4_
安装中文分词插件 IK
Elasticsearch原装分词器会简单地拆分每个汉字,没有根据词库来分词,这样的后果就是搜索结果很可能不是你想要的。这里推荐使用elasticsearch-analysis-ik,支持自定义词库。
- 下载
wget https://github.com/medcl/elasticsearch-analysis-ik/archive/v1.9.4.tar.gz
- 解压
tar -xvf elasticsearch-analysis-ik.tar.gz
- 使用maven打包该java项目
cd elasticsearch-analysis-ik-1.9.4 mvn package
- 在plugins目录下创建ik目录,并将打包好的IK插件解压到其中
mkdir /usr/share/elasticsearch/plugins/ik unzip target/releases/elasticsearch-analysis-ik-1.9.4.zip -d /usr/share/elasticsearch/plugins/ik/
elasticsearch-analysis-ik 的配置文件在
~/{es_root}/plugins/ik/config/ik/
目录,很多都是词表,直接用文本编辑器打开就可以修改,改完记得保存为 utf-8 格式。
现在再启动 Elasticsearch 服务,如果看到类似下面这样的信息,说明 IK Analysis 插件已经装好了
plugins [analysis-ik]
使用 Elasticsearch
在使用之前,先大概了解下ES的特点:
网上通常会将Elasticsearch和传统关系型数据库Mysql做一下类比:
MySQL | Elasticsearch |
---|---|
Database(数据库) | Index (索引) |
Table(表) | Type (类型) |
Row (行) | Document (文档) |
Column (列) | Field (字段) |
Schema (方案) | Mapping (映射) |
Index (索引) | Everything Indexed by default (所有字段都被索引) |
SQL (结构化查询语言) | Query DSL (查询专用语言) |
Elasticsearch不仅仅是全文搜索:
- 分布式的实时文件存储,每个字段都被索引并可被搜索
- 分布式的实时分析搜索引擎
- 可以扩展到上百台服务器,处理PB级结构化或非结构化数据
分布式、实时、每个字段、PB级,有点不明觉厉~ 不要慌,刚认识不熟悉很正常,慢慢接触,自然就熟络了,stop getting off track(回归正题),想要详细认识ES,请移步Elasticsearch权威指南,接下来就是一步步将ES集成进项目当中:
1. 使用package
可以直接使用官方提供的package,由于不想花时间重复造轮子,我直接使用进一步封装的第三方package。在github上有好几个可用的,我选了Elasticquent,部分是因为名字和laravel的Eloquent比较搭(笑...)。Elasticquent提供了简洁好用的trait,直接集成进你的Model里,例如Article:
...
use Elasticquent\ElasticquentTrait;
class Article extends Model
{
use ElasticquentTrait;
...
}
然后就可以优雅的使用Elasticsearch了,具体如何安装使用,请参考Elasticquent的说明文档。
2. 配置Mapping
关于Mapping(映射),我找到了一篇专门介绍它的文章(传送们),通俗易懂。
文章中提到,mapping不仅告诉ES一个field中是什么类型的值, 它还告诉ES如何索引数据以及数据是否能被搜索到。
Got it! 也就是说,如果我们不配置mapping,那ES就不会知道我们是想让它按照IK的分词方式来进行索引咯~
到这里,不得不说这是一个坑,目前网上的很多资料因为使用的是老版本的ES和IK,所以index和mapping的配置一般都放在es的配置文件yml当中。但我按照那种配置方法,并没有达到预期的分词效果,ES还是简单粗暴的将汉字一个个的切开,屡败屡战折腾两天之后,终于想到试着使用Elasticquent说明文档里在Model中配置mapping的方式,果然,豁然开朗:
curl -XGET 'http://localhost:9200/_analyze?analyzer=ik&pretty=true&text=%e4%bd%a0%e5%a5%bd%e9%ba%a6%e8%82%af%e5%85%88%e7%94%9f'
{
"tokens" : [ {
"token" : "你好",
"start_offset" : 0,
"end_offset" : 2,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "麦",
"start_offset" : 2,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 1
}, {
"token" : "肯",
"start_offset" : 3,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 2
}, {
"token" : "先生",
"start_offset" : 4,
"end_offset" : 6,
"type" : "CN_WORD",
"position" : 3
}]
}
附上我的mapping配置代码
protected $mappingProperties = array(
'title' => array(
'type' => 'string',
'analyzer' => 'ik_max_word'
),
'content' => array(
'type' => 'string',
'analyzer' => 'ik_max_word'
)
);
可以看出,我告诉ES,我的title和content字段是string类型而且请按照ik的分词方式帮我检索。
3. 创建索引
直接使用Elasticquent提供的createIndex方法创建,如果想把现有文档全部索引,可以使用addAllToIndex方法,简单愉快。
Article::createIndex($shards = null, $replicas = null);
Article::addAllToIndex();
4. 增删改查
在你的控制器里的增删改查方法中,将Elasticquent提供的相应操作索引的方法依次加上即可,完成之后,那么你对文档的操作就会同步ES的索引了。具体代码请直接移步Elasticquent开源项目中trait里的代码就好,这里不再贴出。
写在最后
在此之前,了解过sphinx,使用过配置好的xunsearch,但真正自己从零开始研究全文搜索引擎还是头一次,中间遇到了许多坑,虽然被坑郁闷,但也感谢这些坑,毕竟越过去就会有快感。写这篇文章一来作为纪念和起点,二来希望能多少对别人有点帮助,因为我也是看过好多相关的文章才一点点将ES搭建完成,在这里感谢那些乐于分享的前辈。
当然,Elasticsearch功能很强大,各种插件各种配置,这篇文章需要完善的地方还有很多,后期会不断更新,如果文中有错误或者不严谨的地方,欢迎留言交流。
PS. 最后贴出我项目中的Dockerfile,方便感兴趣的同学使用。
原文链接:https://macken.me/article/elasticsearch-fo...
参考资料
- Elasticsearch权威指南
- 为你的站点插上ElasticSearch的翅膀
- ElasticSearch安裝中文分詞
- elasticsearch中的mapping简介
- 使用 Elasticsearch 实现博客站内搜索
- elasticsearch-analysis-ik
- Elasticquent
本作品采用《CC 协议》,转载必须注明作者和本文链接
写得很好 质量很高!
@我叫红领巾 谢谢支持!:smile:
很棒,已加精
@Summer 多谢龙哥~
一定要和业务安装到一起吗?
@FreeDKR 有什么更好的见解么?
实战派!Cool !
@nophp 不了解所以问问,因为很多时候多节点,如果每台机器上都装一个ES服务,觉得不太可能,一定有方法起一个服务公用的方法吧?
@FreeDKR 恩,这个我不清楚,同问。
@FreeDKR
@nophp
如果搜索业务量大了,单台服务器同时作为业务和搜索显然不科学。13年的时候我在的那家公司索引服务器是单独的一台,数据库两台。当时的情况是每天10万IP,
Lucene
是货真价实的高性能。配置很简单,
/etc/elasticsearch/elasticsearch.yml
( Mac 为/usr/local/etc/elasticsearch/elasticsearch.yml
) 打开 Network 下面的network.host
注释network.host: 0.0.0.0
,这样就可以公网访问了,如果是内容,改为对应的 Ip 地址。@zhuzhichao +1:

然后再这配置上那台索引服务器的ip地址即可。
@nophp 端口也可以改,哈哈
http.port: 9988
@zhuzhichao 为啥一定要是9988呢,求教~
@nophp 这个没有别的意思,你想多了 ,本来想写成 998 呢,但是一想 1023 之前的(包含)的端口不建议使用,就又写了个8。:sweat_smile:
@zhuzhichao :sweat_smile:,那9200呢...
高质量文章啊 :+1:
感谢分享 现在ES用的比较多啊
文笔不错哦,学习了!
新浪云提供的elasticsearch 比较符合中国用户。其实algolia比elasticsearch更快更好,只是服务器在国外,不太适合国内的用户。
@bluetoothswh algolia 确实很赞
啊,我之前装这个装到想死啊。怒赞!我回头再试试!
@JokerLinly 直接使用 elasticsearch-rtf 也可~
@Macken 安装了 elasticsearch-rtf ,但是好像不能分词。比如。我的数据库里面有牛肉,已经导入索引。我搜牛可以搜到,搜索牛肉就没有。这种是分词的问题吗?
建议筒子们直接看官网的权威指南不要看文中推荐的那个(可能因为阅读习惯的问题吧我觉得官网的排版更清楚舒服些)。
链接: https://www.elastic.co/guide/cn/elasticsea...
大大,这个报错有遇到过吗?我确认已经启动了 es
很棒
如何给elasticsearch 增加密码?
其实我想知道 Elasticsearch 用哪个工具 与 mysql 同步吗?
@凌寒傲雪 直接 github 上搜轮子,例如针对 laravel 的 https://github.com/cviebrock/laravel-elast...
@Macken 首先非常感谢您的回复, 但是我需要 mysql 同步的方案,第三方插件,难度有点大,涉及到我的技术忙点,而且实时同步这个问题,一直都困扰着我,毕竟是旧项目,该起来也有点难度呢。