Elasticsearch学习方法以及复杂数据类型的映射

来源:互联网 发布:监控客户端软件 编辑:程序博客网 时间:2024/06/05 12:46

概述

Elasticsearch是一个基于Lucene的搜索服务器。以下简称ES,版本为2.3左右的。

ES的版本比较多,目前已经到了5.3版本,但是很多公司都没有使用最新版本,我所在的公司也是如此。在没有接触ES之前,我不知道这个全文索引的框架,加上我英文不好,学习的时候真的给我带了不少的问题,踩了很多的坑。下面,我将从一个0基础的角度来介绍我学习ES的过程。感谢我的指导老师骞哥、祥哥。

一、如何学习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时遇到的问题

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

三、一些ES的概念

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不久,因此上面说的步骤不一定适合你,上面步骤是我经验丰厚的同事教的方法,我根据他教的方法终结出来的。这里我只是提供我自己学习的路线,你可以自己根据自己的能力调整。

五、Mapping映射(高级)

虽然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.startDate" : {                  "from" : "2017-03-05",                  "to" : null,                  "format" : "yyyy-MM-dd",                  "include_lower" : true,                  "include_upper" : true                }              }            }, {              "range" : {                "schedule_info.date.endDate" : {                  "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会以字符串的形式比较,从而得不到正确的结果。在此例子中,我将时间转化成为了整型,方便查找时间区间。

由于小编能力有限,如有错误,请指正,谢谢合作!

1 0
原创粉丝点击