欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ElasticSearch 学习(一)——安装配置,基本概念与操作

程序员文章站 2022-07-01 09:28:21
...

Elastic Search 学习

安装与环境配置

安装包下载

安装环境为macOS,直接去官网进行下载解压安装,但是下载很慢,是外网。

官网下载网址:https://www.elastic.co/cn/downloads/elasticsearch

也可以直接使用brew安装,网上都有教程。

可视化插件选择

直接去chrome商店下载Elastic Search head插件,是一款管理ES的可视化插件。

https://chrome.google.com/webstore/detail/elasticsearch-head/ffmkiejjmecolpfloofpjologoblkegm

相关概念

与MySQL进行对比,两者对应的概念如下

Relational DB DataBase Tables Rows Columns
Elastic Search Indices Types Documents Fields

索引 index

具有相似特征的文档集合。通常会为具有一组共同字段的文档定义一个类型。例如,运营一个博客平台,将所有数据存储到一个索引中,在这个索引中,用户数据是一个类型,博客文章是一个类型,评论数据是一个类型。

字段 field

相当于数据表字段,对文档数据根据不同属性分类标识。

映射 mapping

对处理数据的方式和规则方面做一些限制。

索引基本操作

创建一个索引

PUT /索引名/[类型名]/文档id	//类型名会被弃用,默认为_doc
{
	"name":"zhangsan",
	"age":18
}

创建完索引之后,数据也成功添加,也可以在head中进行数据预览。

此时发现 name age等字段没有设置类型,可以指定字段的类型。

PUT /test1	 //此时只有索引,没有后续参数,

{
    "mappings":{
        "properties":{
            "name":{
                "type":"text"
            },
            "age":{
                "type":"long"
            },
            "birthday":{
                "type":"date"
            }
        }
    }
}

创建了具体的数据规则。

获取索引信息

通过get请求获取具体的信息,如果文档字段没有指定,ES会默认配置字段类型

GET /test1

通过 GET _cat/ 命令,可以获得ES中的很多信息

修改索引信息

  • 直接重新PUT一遍

  • 使用POST命令

  • POST /索引名称/类型名称/文档id/_update
    

删除索引

DELETE /索引名称  	//直接删除索引库
DELETE /索引名称/类型名称/文档id		//删除索引中的某个文档

文档操作

添加数据

PUT /test/user/1

{
  "name":"zhangsan",
	"age":18,
  "tag":["高","富","帅"]
}

查询数据

GET /test/user/1 

更新数据

PUT /test/user/1	//缺失的字段会被置空

{
  "name":"wangwu",
  "age":18,
  "tag":["白","富","美"]
}

//更推荐POST
POST /test/user/1/_update

{
  "name":"wangwu",
  "age":18,
  "tag":["白","富","美"]
}

搜索搜索操作

简单条件查询(所有查询都用GET操作)
GET /test/user/_search?q=name:zhangsan //精确匹配查找name为zhangsan的

查询结果

{
    "took": 2,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {															//hits对象Java中的Hits对象
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": 0.9808291,		//最大的得分值
        "hits": [
            {															//查询出来的具体文档,都可以通过遍历得到
                "_index": "test",
                "_type": "user",
                "_id": "2",
                "_score": 0.9808291,
                "_source": {
                    "name": "zhangsan",
                    "age": 18,
                    "tag": [
                        "高",
                        "富",
                        "丑"
                    ]
                }
            }
        ]
    }
}

查询结果中的score代表查询结果的匹配程度高低

复杂查询(排序,分页,高亮,模糊查询,精准查询)
GET /test/user/_search

{
  "query":{
      "match":{
          "name":"%zhangsan%"
      }
  }
}

指定查询结果展示字段
{
  "query":{
      "match":{
          "name":"%zhangsan%"
      }
  }
  "_source":["name","age"]		//只需要name和age
}
按字段排序展示查询结果,并且进行分页
{
  "query":{
      "match":{
          "name":"张"	//按张进行匹配,张三,张四,张三丰这种分词后都带张,都可以匹配到
      }
    },
    "sort":[	  //sort表示排序,asc按升序查询
        {
            "age":{
              "order":"asc"
            }
        }
    ],
    "from":0,	//从第几条数据开始
    "size":2	//每页展示几条数据
}
布尔值查询,可以进行多条件查询
{
  "query":{
      "bool":{
          "must":[
              {
                  "match":{
                      "name":"张"
                  }
              },
              {
                  "match":{
                      "age":18
                  }
              }
          ]
      }
    }
}
  • must (and),所有条件都要符合,where name = “张” and age=18
  • should (or),或操作,where name = “张” or age = 18
  • must_not (not),否操作,不等于
过滤
{
  "query":{
      "bool":{
          "should":[
              {
                  "match":{
                      "name":"张"
                  }
              },
              {
                  "match":{
                      "age":18
                  }
            }
          ],
          "filter":{			//采用filer关键字,与should,must等同级
              "range":{
                  "age":{
                      "gt":10		//可以进行多个 gt lt lte gte 等同时过滤
                  }
              }
            }
        }
    }
}
  • gt大于
  • gte大于等于
  • lt小于
  • lte小于等于
匹配多个条件
{
  "query":{
      "match":{
          "tag":"穷 丑"		//直接在搜索关键字字段里用空格隔开,含有 穷 丑 的都能匹配
      }
    }
}
查询结果
{
    "took": 5,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 7,		//总共有7条数据符合,也可以按照匹配分值进行筛选
            "relation": "eq"
        },
        "max_score": 1.6063561,		//最匹配的分数为 1.61,按分数高低排列
        "hits": [
            {
                "_index": "test",
                "_type": "user",
                "_id": "8",
                "_score": 1.6063561,	//可以看到包含了 穷 丑 两个
                "_source": {
                    "name": "张四",
                    "age": 21,
                    "tag": [
                        "挨",
                        "穷",
                        "丑"
                    ]
                }
            },
            {
                "_index": "test",
                "_type": "user",
                "_id": "1",
                "_score": 1.2809337,	//只包含穷,分数降低
                "_source": {
                    "name": "lisi",
                    "age": 23,
                    "tag": [
                        "矮",
                        "穷",
                        "帅"
                    ]
                }
            },
            {
                "_index": "test",
                "_type": "user",
                "_id": "2",
                "_score": 0.3254224,
                "_source": {
                    "name": "zhangsan",
                    "age": 18,
                    "tag": [
                        "高",
                        "富",
                        "丑"
                    ]
                }
            },
            {
                "_index": "test",
                "_type": "user",
                "_id": "4",
                "_score": 0.3254224,
                "_source": {
                    "name": "张三",
                    "age": 18,
                    "tag": [
                        "高",
                        "富",
                        "丑"
                    ]
                }
            },
            {
                "_index": "test",
                "_type": "user",
                "_id": "5",
                "_score": 0.3254224,
                "_source": {
                    "name": "李四",
                    "age": 18,
                    "tag": [
                        "高",
                        "富",
                        "丑"
                    ]
                }
            },
            {
                "_index": "test",
                "_type": "user",
                "_id": "6",
                "_score": 0.3254224,
                "_source": {
                    "name": "张三丰",
                    "age": 26,
                    "tag": [
                        "高",
                        "富",
                        "丑"
                    ]
                }
            },
            {
                "_index": "test",
                "_type": "user",
                "_id": "7",
                "_score": 0.3254224,
                "_source": {
                    "name": "王五",
                    "age": 21,
                    "tag": [
                        "高",
                        "富",
                        "丑"
                    ]
                }
            }
        ]
    }
}
精确查询

term 查询是直接通过倒排索引进行精确查找

match 会使用分词器解析

两个类型 text 和 keyword

text可以被分词器解析;而keyword不能被分词器解析,只能作为整体。以下为示例

//先创建一个testdb作为测试索引
PUT /testdb 

{
  "mappings":{
    "properties":{
      "name":{
        "type":"text"
      },
      "desc":{
        "type":"keyword"
      }
    }
  }
}

PUT /testdb/_doc/1			//插入两条数据

{
  "name":"爱新觉罗张三 name",
	"desc":"爱新觉罗张三 desc"
}

PUT /testdb/_doc/2			

{
  "name":"爱新觉罗张三 name",
	"desc":"爱新觉罗张三 desc2"
}

可以先看一下分析器对于 keyword 和 standard的分析区别

GET /_analyze

//body:
{
    "analyzer":"keyword",
    "text":"爱新觉罗张三 name"
}

//结果:
{
    "tokens": [
        {
            "token": "爱新觉罗张三 name",
            "start_offset": 0,
            "end_offset": 11,
            "type": "word",
            "position": 0
        }
    ]
}

//body:
{
    "analyzer":"standard",
    "text":"爱新觉罗张三 name"
}

//结果:
{
    "tokens": [
        {
            "token": "爱",
            "start_offset": 0,
            "end_offset": 1,
            "type": "<IDEOGRAPHIC>",
            "position": 0
        },
        {
            "token": "新",
            "start_offset": 1,
            "end_offset": 2,
            "type": "<IDEOGRAPHIC>",
            "position": 1
        },
        {
            "token": "觉",
            "start_offset": 2,
            "end_offset": 3,
            "type": "<IDEOGRAPHIC>",
            "position": 2
        },
        {
            "token": "罗",
            "start_offset": 3,
            "end_offset": 4,
            "type": "<IDEOGRAPHIC>",
            "position": 3
        },
        {
            "token": "张",
            "start_offset": 4,
            "end_offset": 5,
            "type": "<IDEOGRAPHIC>",
            "position": 4
        },
        {
            "token": "三",
            "start_offset": 5,
            "end_offset": 6,
            "type": "<IDEOGRAPHIC>",
            "position": 5
        },
        {
            "token": "name",
            "start_offset": 7,
            "end_offset": 11,
            "type": "<ALPHANUM>",
            "position": 6
        }
    ]
}
  • keyword 不会被分词器分析,会将其当作整体

那么我们对上面添加的 两条数据进行搜索实验:

{
  "name":"爱新觉罗张三 name",
	"desc":"爱新觉罗张三 desc"
}		
{
  "name":"爱新觉罗张三 name",
	"desc":"爱新觉罗张三 desc2"
}
//其中 name 是 text ,desc 是 keyword

GET /_search
{
    "query":{
        "term":{
            "name":"爱"
        }
    }
}

//结果:
{
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 2,
            "relation": "eq"
        },
        "max_score": 0.18232156,
        "hits": [
            {
                "_index": "testdb",
                "_type": "_doc",
                "_id": "1",
                "_score": 0.18232156,
                "_source": {
                    "name": "爱新觉罗张三 name",
                    "desc": "爱新觉罗张三 desc"
                }
            },
            {
                "_index": "testdb",
                "_type": "_doc",
                "_id": "2",
                "_score": 0.18232156,
                "_source": {
                    "name": "爱新觉罗张三 name",
                    "desc": "爱新觉罗张三 desc2"
                }
            }
        ]
    }
}
//name是text格式,“爱新觉罗张三 name” 被分词解析,所以查询任一个中文或英文单词 name 都有结果返回

GET /_search
{
    "query":{
        "term":{
            "desc":"爱"
        }
    }
}

//结果
{
    "took": 1,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 0,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    }
}
//desc是keyword类型,爱新觉罗张三 desc 没有被分词,所以查单个汉字无结果,只有查整体才行,如下:

{
    "query":{
        "term":{
            "desc":"爱新觉罗张三 desc"
        }
    }
}

多个值匹配的精确查询

先放入两条数据

PUT /testdb/_doc/3
{
    "t1":"22",
    "t2":"2020-4-6"
}

PUT /testdb/_doc/4
{
    "t1":"33",
    "t2":"2020-4-7"
}

//进行多个值精确匹配查询

GET /testdb/_search

// 查询	t1 为 22 或 33的
{
    "query":{
        "bool":{
            "should":[
                {
                    "term":
                    {
                        "t1":22
                    }
                },
                {
                    "term":
                    {
                        "t1":33
                    }
                }
            ]
        }
    }
}
高亮关键字

直接查看实现高亮的方法,实际上是为需要高亮的文本添加html标签以修饰

GET /test/user/_search

{
  "query":{
      "match":{
          "name":"张"
      }
    },
    "highlight":{	//配置高亮的一些参数														
        "pre_tags":"<p class='key' style='color:red'>" ,	//高亮标签前缀,默认 em		
        "post_tags":"</p>" ,	//高亮标签后缀															
        "fields":{		//高亮的区域																					
            "name":{}
        }
    }
}

综上,ES可以做到:

  • 匹配,按照条件匹配,精确匹配,区间范围匹配,匹配字段过滤
  • 多条件查询,高亮查询

下一章将ES集成到SpringBoot中去。