Elasticsearch是一个基于Lucene的搜索服务器。以下简称ES,版本为2.3左右的。
ES的版本比较多,目前已经到了5.3版本,但是很多公司都没有使用最新版本,我所在的公司也是如此。在没有接触ES之前,我不知道这个全文索引的框架,加上我英文不好,学习的时候真的给我带了不少的问题,踩了很多的坑。下面,我将从一个0基础的角度来介绍我学习ES的过程。感谢我的指导老师骞哥、祥哥。
ES的中文文档并不多,在加上ES的版本很多,给翻译带来了很大的工作量。但是,我在学习过程中找到了一些文档和资料,可以快速的让你了解ES是什么,该怎么使用。
1.ES官方文档
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html
学习ES的官方文档中的Getting Started,可以让你对ES的概念有个大概的了解,包括ES的一些基本概念,ES的安装,索引,查询等方面的知识。但是对于英文不好的人来说,要理解这些概可能就需要看上个一两天,都还不一定能懂。那么请看条例2。
2.Getting Started的中文博客地址
http://blog.csdn.net/cnweike/article/details/33736429
这篇博客将Getting Started详细的翻译了一遍,结合上英文,再去理解,就比较容易了。
3.ES的中文翻译社区地址(ES权威指南)
https://es.xiaoleilu.com/index.html
这ES权威指南书籍的电子文档,这个网站已经翻译了很多章节的内容,如果你对博客中给出的翻译不满意,可以结合本网站学习。这个网站有个毛病,不知道是电脑字库渲染问题还是文档本身的问题,翻译中会有很多的字是错的。另一个毛病便是切换文档时需要等待很久,因此,需要你有足够的耐心。ES权威指南有一个最大的优点,它选择人们经常用的东西翻译,这给开发带来了极大的便利。
4.ES英文官网文档学习路线
如果你急需在较短的时间内使用ES,那么你可以按着下面的路线进行快速入门,并且学习一些高级的东西。下面的学习路线是拥有多年开发经验同事给我规划的,希望对你有用。我公司使用的ES版本是2.3,并且封装了自己的框架。因此,你在查看文档时,也需要查看相应的版本,版本不同,文档的结构会有所变化。
① Getting Started 里的所有内容;
② Setup Elasticsearch 里的所有内容;
③ Document APIs 里的所有内容;
④ Search APIs 下的 Search、URI Search、Request Body Search;
⑤ Query DSL 下的 Query and filter context、Match All Query、Full text queries下的Match Query, Compound queries下的 Bool Query, Joining queries下的 Nested Query。
⑥ Term level queries下的 Term Query、Terms Query、Rangge Query。这在查询时会用到。
⑦ Mapping下Field datatypes下的Array datatype、Binary datatype、Range datatype、Boolean datatype、Date datatype、Object datatype、String datatype、Text datatype;这里根据自己想买需求可多看一些其他的,这里讲解的是ES所支持的数据类型。
上面给出的,便是我接触ES的学习路线,说实话,第一次接触ES,我不仅看完了上面的全部,还看了很多。才把ES弄明白了一点点。
ES的搭建在我看来,懂点Linux的人基本上不成问题,但是像我这种菜菜,就遇到了好多坑。不过我所遇到错误的原因都是权限问题。ES官网明确的说了一点,不要使用root用户启动,这是致命的。
第二个问题是,ES的压缩包解压之后,就可以直接使用了,如果你对文件夹做权限的更改,那么,启动的时候就会报找不到Java环境等各种错误,起初我以为是我没有搭建Java环境,到头来发现,并不是,遇到这个问题时,使用如下方式解决问题:
[yh@centos bin]$ sudo chown -R elasticsearc安装文件夹 yh.yh
例如: sudo chown -R elasticsearch yaohong.yaohong(这个是用户)
执行以上命令之后,那么Elasticsearch就可以正常启动了,如果遇到别的问题,那么不好意思,百度吧!
启动ES的方法
解压文件之后,进入bin目录,然后执行以下命令,ES便启动了。
[yh@centos bin]$ ./elasticsearch
如果想在后台启动,使用-d参数,命令如下:
[yh@centos bin]$ ./elasticsearch -d
如果不是后台启动,你将看到如下信息,如果没有如下信息,说明ES启动失败了!
[2017-04-24 10:36:53,706][INFO ][node ] [Mist Mistress] version[2.4.4], pid[12159], build[fcbb46d/2017-01-03T11:33:16Z]
[2017-04-24 10:36:53,707][INFO ][node ] [Mist Mistress] initializing ...
[2017-04-24 10:36:55,021][INFO ][plugins ] [Mist Mistress] modules [lang-groovy, reindex, lang-expression], plugins [], sites []
[2017-04-24 10:36:55,069][INFO ][env ] [Mist Mistress] using [1] data paths, mounts [[/ (rootfs)]], net usable_space [11.9gb], net total_space [19.5gb], spins? [unknown], types [rootfs]
[2017-04-24 10:36:55,069][INFO ][env ] [Mist Mistress] heap size [1015.6mb], compressed ordinary object pointers [true]
[2017-04-24 10:36:59,763][INFO ][node ] [Mist Mistress] initialized
[2017-04-24 10:36:59,770][INFO ][node ] [Mist Mistress] starting ...
[2017-04-24 10:37:00,014][INFO ][transport ] [Mist Mistress] publish_address {127.0.0.1:9301}, bound_addresses {127.0.0.1:9301}
[2017-04-24 10:37:00,031][INFO ][discovery ] [Mist Mistress] elasticsearch/a-VF8e_uQZ2y0k-wB_eeug
[2017-04-24 10:37:03,389][INFO ][cluster.service ] [Mist Mistress] detected_master {Anelle}{K2u_6PgETsG5BifXQxfO2w}{127.0.0.1}{127.0.0.1:9300}, added {{Anelle}{K2u_6PgETsG5BifXQxfO2w}{127.0.0.1}{127.0.0.1:9300},}, reason: zen-disco-receive(from master [{Anelle}{K2u_6PgETsG5BifXQxfO2w}{127.0.0.1}{127.0.0.1:9300}])
[2017-04-24 10:37:03,855][INFO ][http ] [Mist Mistress] publish_address {127.0.0.1:9201}, bound_addresses {127.0.0.1:9201}
[2017-04-24 10:37:03,860][INFO ][node ] [Mist Mistress] started
如果你是后台启动,将看不到任何输出,除非出错了,可以使用如下命令,查看都端口情况:
[yh@centos bin]$ netstat -apn | grep 9200
1.ES中的Bool查询有三种状态,分别是must,should,must_not。说实话,我都怀疑我的语文是体育老师教的,当时我看到这个时,想了很久都没有搞懂。在加上看的是英文,我更懵逼了。如果你有SQL语言的基础,那么就很好理解了。
① must 相当于 SQL 的 and条件,比如你用SQL查询价格,你会写出如下sql语句:
select * from table_name where id = 1000 and price = 50;
这样的语句就相当于ES的must查询。
② shoud相当于SQL 的 or条件,例如:
select * from table_name where id = 1000 or price = 50;
③ must_not 相当于SQL的not in,例如:
select * from table_name where id not in(1000);
must_not即不包含某某。
对于大于等于,区间值等,API的文档中有详细的说明。
如果你想知道更多的概念,那么请点击我上面说明的连接地址,他们讲解的更清楚,我不在造轮子。
1.学习ES的相关基础知识和概念;
2.了解项目需求;
3.考虑ES的所需功能是否能够解决当前的项目需求;
4.考虑之后,部署ES,如果能力可能,可自行封装一层,原生的ES操作比较复杂,数据拼接容易出错且不好维护;
5.编写Mapping,建立索引;
6.导入数据;
7.数据导入之后便可查询、重索引等各种测试,如果没有数据,一切都是瞎忙活;
8.应用到实际项目中。
由于小编也是刚接触ES不久,因此上面说的步骤不一定适合你,上面步骤是我经验丰厚的同事教的方法,我根据他教的方法终结出来的。这里我只是提供我自己学习的路线,你可以自己根据自己的能力调整。
虽然ES可以根据数据的格式自动创建Mapping,他将所有的对象都映射成Object,但很多时候是不满足项目需求的,基础的Mapping映射我就不解释,官方文档比我说得清楚,不需要你看英文说明,仅看代码就秒懂,并且网上一搜一大堆。我在做项目时遇到的映射,在网上并没有找到。首先,请看下面这个json数据,我们需求是,能够查询字段”schedule_info”中时间区间或者日期区间,看到这个json你也许知道,sql是做不到的(”schedule_info字段是以json字符串保存到数据库中的”),而ES是可以的,但是ES要实现这个功能,需要用到Nested查询,那么在写Mapping时,就必须将其转化为对象。
{
"id": 1000017,
"status": 0,
"name": "HHH",
"daily_budget": 410000,
"schedule_info": {
"date": [
{
"start": "2017-04-20",
"end": "2017-04-20"
},
{
"start": "2017-04-20",
"end": "2017-04-20"
}
],
"time": [
{
"start": "00:00",
"end": "23:59"
},
{
"start": "00:00",
"end": "23:59"
}
]
},
"serving_speed": 0,
"create_time": 1492694481227,
"start_schedule": 1492694481227,
"end_schedule": 1499994481227,
"create_user": "admin",
"update_user": "unknown"
}
“schedule_info”字段包含了一个date和time两个属性,而这两个属性是都是数据,那么在写mapping时,该怎么写,我在做项目时,琢磨了一天,才弄明白ES的对象嵌套映射。下面是我的mapping。
{
"order": 0,
"template": "Yaohong-plan-*",
"settings": {
"index": {
"number_of_replicas": "1",
"number_of_shards": "5",
"refresh_interval": "1s"
}
},
"mappings": {
"_default_": {
"properties": {
"update_user": {
"index": "not_analyzed",
"type": "string" },
"status": {
"type": "integer" },
"end_schedule": {
"format": "yyyy-MM-dd HH:mm:ss||epoch_millis",
"type": "date" },
"serving_speed": {
"type": "integer" },
"id": {
"type": "long" },
"update_time": {
"format": "yyyy-MM-dd HH:mm:ss||epoch_millis",
"type": "date" },
"start_schedule": {
"format": "yyyy-MM-dd HH:mm:ss||epoch_millis",
"type": "date" },
"daily_budget": {
"type": "integer" },
"create_time": {
"format": "yyyy-MM-dd HH:mm:ss||epoch_millis",
"type": "date" },
"create_user": {
"index": "not_analyzed",
"type": "string" },
"schedule_info": {
"type":"nested",
"properties":{ "date":{ "properties":{ "start":{ "type":"date", "format":"yyyy-MM-dd||epoch_millis" }, "end":{ "type":"date", "format":"yyyy-MM-dd||epoch_millis" } } }, "time":{ "properties":{ "start":{ "type":"integer" }, "end":{ "type":"integer" } } } } }
},
"_all": {
"enabled": false
}
}
},
"aliases": {
"Yaohong-plan-active": {}
}
}
那么如果我需要查询日期在某个区间怎么去查询呢?请看下面的查询语句:
{
"bool" : {
"must" : [ {
"term" : {
"status" : "0"
}
}, {
"nested" : {
"query" : {
"bool" : { "filter" : [ { "range" : { "schedule_info.date.start" : { "from" : "2017-03-05", "to" : null, "format" : "yyyy-MM-dd", "include_lower" : true, "include_upper" : true } } }, { "range" : { "schedule_info.date.end" : { "from" : null, "to" : "2017-09-12", "format" : "yyyy-MM-dd", "include_lower" : true, "include_upper" : true } } } ] } },
"path" : "schedule_info"
}
} ],
"should" : {
"match" : {
"name" : {
"query" : "YangHong",
"type" : "boolean" }
}
}
}
}
从查询语句可以看出,ES对对象进行了扁平化的处理方式,如schedule_info.date.endDate,基于别的对象或者是数组的映射,官方文档都有很详细的说明,我给出的例子,在官方文档是没有的,因此分享给大家,当你看完这个例子,相信别的复杂映射都可以解决了。
另外需要说明的是,ES查询日期类型时,其查询格式必须与Mapping映射时的格式一模一样,否则会出错,对于单纯的时间查询,需要转化成可比较的数据类型,像“06.30”这样的时间数据,ES会以字符串的形式比较,从而得不到正确的结果。在此例子中,我将时间转化成为了整型,方便查找时间区间。
由于小编能力有限,如有错误,请指正,谢谢合作!