最近因为工作需要,我慢慢接触了有关elasticsearch的知识,接下来我将从一个新手的角度带你入门elasticsearch

1.什么是Elasticsearch?

Elasticsearch是一款基于Lucene的开源搜索引擎,通过简单连贯的RESTful API让全文搜索变得简单并隐藏Lucene的复杂性,使用java开发,他的优势包括但不限于以下几点:

  • 分布式的实时文件存储,每个字段都被索引并可被搜索

  • 实时分析的分布式搜索引擎

  • 可以扩展到上百台服务器,处理PB级结构化或非结构化数据

  • ......

2.什么是RestfulApi?

RestfulApi 是一种软件架构、设计风格、而不是标准,只是提供了一组设计原则和约束条件,基于这个风格设计的软件更简洁,更有层册,更易于实现缓存等机制。至于请求方式可以通过 GET、 POST、 PUT、 PATCH、 DELETE 等方式对服务端的资源进行操作。其中,GET 用于查询资源,POST 用于创建资源,PUT 用于更新服务端的资源的全部信息,PATCH 用于更新服务端的资源的部分信息,DELETE 用于删除服务端的资源。下面通过几个小demo来简单介绍用法:

【GET】 /users # 查询用户信息列表
【GET】 /users/1001 # 查看某个用户信息
【POST】 /users # 新建用户信息
【PUT】 /users/1001 # 更新用户信息(全部字段)
【PATCH】 /users/1001 # 更新用户信息(部分字段)
【DELETE】 /users/1001 # 删除用户信息

3.Elasticsearch的关键词

1.集群

一个集群就是由一个或多个节点组织在一起,它们共同持有你整个的数据,并一起提供索引和搜索功能。一个集群由一个唯一的名字标识,这个名字默认就是“elasticsearch”。这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群。在产品环境中显式地设定这个名字是一个好习惯,但是使用默认值来进行测试/开发也是不错的。

2.节点

一个节点是你集群中的一个服务器,作为集群的一部分,它存储你的数据,参与集群的索引和搜索功能。一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫做“elasticsearch”的集群中,这意味着,如果你在你的网络中启动了若干个节点,并假定它们能够相互发现彼此,它们将会自动地形成并加入到一个叫做“elasticsearch”的集群中。在一个集群里,只要你想,可以拥有任意多个节点。而且,如果当前你的网络中没有运行任何Elasticsearch节点,这时启动一个节点,会默认创建并加入一个叫做“elasticsearch”的集群。

3.索引

可以理解为关系型数据库中的库

4.类型

可以理解为关系型数据库中的表结构ES6以后一个index只能有一个type,为了提高查询效率

5.文档

可以理解为关系型数据库中的记录,文档以JSON格式来表示。注意,尽管一个文档,物理上存在于一个索引之中,档必须被索引/赋予一个索引的type。

6.接近实时

查询索引的文档只有一个轻微的延迟

7.分片与复制

一个索引可以存储超出单个结点硬件限制的大量数据。比如,一个具有10亿文档的索引占据1TB的磁盘空间,而任一节点都没有这样大的磁盘空间;或者单个节点处理搜索请求,响应太慢。 为了解决这个问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片。 在一个网络/云的环境里,失败随时都可能发生,在某个分片/节点不知怎么的就处于离线状态,或者由于任何原因消失了,这种情况下,有一个故障转移机制是非常有用并且是强烈推荐的。为此目的,Elasticsearch允许你创建分片的一份或多份拷贝,这些拷贝叫做复制分片,或者直接叫复制。

4.安装

安装环节我直接摘抄一位大神的步骤(偷懒。。)

Elastic 需要 Java 8 环境。如果你的机器还没安装 Java,可以参考这篇文章,注意要保证环境变量JAVA_HOME正确设置。

安装完 Java,就可以跟着官方文档安装 Elastic。直接下载压缩包比较简单。

$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.5.1.zip
$ unzip elasticsearch-5.5.1.zip
$ cd elasticsearch-5.5.1/ 

接着,进入解压后的目录,运行下面的命令,启动 Elastic。

$ ./bin/elasticsearch

如果这时报错"max virtual memory areas vm.maxmapcount [65530] is too low",要运行下面的命令。

$ sudo sysctl -w vm.max_map_count=262144

如果一切正常,Elastic 就会在默认的9200端口运行。这时,打开另一个命令行窗口,请求该端口,会得到说明信息。

$ curl localhost:9200
{
  "name" : "atntrTf",
  "cluster_name" : "elasticsearch",
  "cluster_uuid" : "tf9250XhQ6ee4h7YI11anA",
  "version" : {
    "number" : "5.5.1",
    "build_hash" : "19c13d0",
    "build_date" : "2017-07-18T20:44:24.823Z",
    "build_snapshot" : false,
    "lucene_version" : "6.6.0"
  },
  "tagline" : "You Know, for Search"
}

上面代码中,请求9200端口,Elastic 返回一个 JSON 对象,包含当前节点、集群、版本等信息。

按下 Ctrl + C,Elastic 就会停止运行。

默认情况下,Elastic 只允许本机访问,如果需要远程访问,可以修改 Elastic 安装目录的config/elasticsearch.yml文件,去掉network.host的注释,将它的值改成0.0.0.0,然后重新启动 Elastic。

network.host: 0.0.0.0

上面代码中,设成0.0.0.0让任何人都可以访问。线上服务不要这样设置,要设成具体的 IP。

5.请求结构

Eg: curl -XGET 'http://localhost:9200/_str?pretty' -d '{ }


6.基本使用


7.重点(查询功能)

# name 在创建类型的时候是keyword  所以没有分词查询
GET clayindex/_doc/_search
{
"query":{
"match": {
"name": "曹操"
}
}
}
#address 创建的时候是text ,所以查询的时候被分词查询,比如 查出所有包含国字的数据
GET clayindex/_doc/_search
{
"query":{
"match": {
"address": "魏国"
}
}
}
#_source 可以设置需要返回需要的字段 select name from ==
GET clayindex/_doc/_search
{
"query":{
"match": {
"address": "魏国"
}
},
"_source":["name"]
}
排序
GET clayindex/_doc/_search
{
"query":{
"match": {
"address": "魏国"
}
},
"_source":["name"],
"sort":[
{"age":{"order":"desc"}},
{"name":{"order":"asc"}}
]
}
分页查询
GET clayindex/_doc/_search
{
"query":{
"match": {
"address": "魏国"
}
},
"_source":["name"],
"sort":[
{"age":{"order":"desc"}},
{"name":{"order":"asc"}}
],
"from":0,
"size":10
} 聚合查询

"aggs":{ #聚合
"avg_grade":{ #聚合一个名叫 grade的字段 聚合函数为avg平均
"avg":{
"field":"grade"
}
},
"vivo_prices":{ #聚合一个名叫 price的字段 聚合函数为sum求和
"sum":{
"field":"price"
}
},
"max_price" : { #聚合一个名叫 price的字段 聚合函数为max求最大
"max" : {
"field" : "price"
}
},
"grades_stats" : { #这是一个多值聚合,它返回 min ,max ,sum ,count ,avg 的组合结果
"stats" : {
"field" : "grade"
}
},
"price_ranges" : { #范围聚合
"range" : {
"field" : "price",
"ranges" : [
{ "to" : 100.0 },
{ "from" : 100.0, "to" : 200.0 },
{ "from" : 200.0 }
]
}
},
"vivo":{ #先过滤再聚合
"filter":{
"term":{
"category":"vivo"
}
},
"aggs":{
"avg_price":{
"avg":{
"field":"price"
}
}
}
},
"genres" : { #相当于关系型数据库中的分组(group by)
"terms" : {
"field" : "genre",
"size" : 2 #size 可以用于指定返回多少个term bucket
}
}
}

布尔值查询
条件1 and 条件2

must =>and

GET clayindex/_doc/_search
{ "query":{
"bool": {
"must": [
{
"match": {
"address": "魏国"
}

},{
"match": {
"name": "曹操"
}
}
]
}
},
"_source":["name"],
"sort":[
{"age":{"order":"desc"}},
{"name":{"order":"asc"}}
],
"from":0,
"size":2
} 条件1 or 条件2
should => or

GET clayindex/_doc/_search
{

"query":{
"bool": {
"should": [
{
"match": {
"address": "魏国"
}
},{
"match": {
"name": "曹操"
}
}
]
}
},
"_source":["name"],
"sort":[
{"age":{"order":"desc"}},
{"name":{"order":"asc"}}
],
"from":0,
"size":10
} 排除 must_not

#查询名字不是曹操的信息
GET clayindex/_doc/_search
{
"query":{
"bool": {
"must_not": [
{
"match": {
"name": "曹操"
}
}
]
}
}
} 数据过滤filter
gt 大于
gte 大于等于
lt 小于
lte 小于等于!
# 查询名字是曹操,然后年龄大于等于10 小于等于30
GET clayindex/_doc/_search
{
"query":{
"bool": {
"must": [
{
"match": {
"name": "曹操"
}
}
],
"filter": {
"range": {
"age": {
"gte": 10,
"lte": 20
}
}
}
}
}
} 配备多个条件查询

# 使用空格隔开,查询是吴国又是魏国的 ,只要满足一个条件就可以了
GET clayindex/_doc/_search
{
"query":{
"match":{"address":"吴国 魏国 "}
}
} 精确查询
直接根据倒序索引精确查询

match和term的区别
match,会使用分词器解析!注意:先分词然后再去查询
term ,直接查询精确的 temrs, 直接通过多个条件查询精确结果 #在定义的时候可以指定查询时候的分词规则,注意只有text类型才是支持的,而且分词类型和搜索分词类型必须都要设置
PUT /clayindex3
{
"mappings": {
"properties": {
"name":{
"type": "keyword"
},
"address":{
"type": "text",
"analyzer": "standard",
"search_analyzer": "standard"
},
"age":{
"type": "integer"
}
}
}
}

#分词和搜索分词的类型可以不同
PUT /clayindex4
{
"mappings": {
"properties": {
"name":{
"type": "keyword"
},
"address":{
"type": "text",
"analyzer": "ik_max_word",
"search_analyzer": "standard"
},
"age":{
"type": "integer"
}
}
}
}
#注意,针对 text 类型区分精确查询和模糊查询,如果是keyword类型的话不区分,因为没有给keyword类型做分词
#根据魏国模糊查询,包含魏和国的都可以查询
GET /clayindex/_doc/_search
{
"query":{
"match": {
"address":"魏国"
}
}

}

#精准查询 查不出数据,因为分词默认分成了 魏和国,所以 可以试试查查魏或者国
GET /clayindex/_doc/_search
{
"query":{
"term": {
"address":"魏国"
}
}

}
#keyword 类型不会被分词的
GET _analyze
{
"analyzer": "keyword",
"text": "魏国"
}

#这是默认情况下的分词情况
GET _analyze
{
"analyzer": "standard",
"text": "魏国"
}
多个值得精确查询-》直接根据倒序索引来查的

#根据名字是曹操,而address 是国的索引
GET clayindex/_doc/_search
{

"query":{
"bool": {
"must": [
{
"term": {
"address": "国"
}

},{
"term": {
"name": "曹操"
}

}
]

}
},
"_source":["name"],
"sort":[
{"age":{"order":"desc"}},
{"name":{"order":"asc"}}
],
"from":0,
"size":2
}