seq搜索引擎优化至少包括那几步?(开源ElasticsearchType类型Document可以分组吗?(一)(组图))
优采云 发布时间: 2022-02-01 04:15seq搜索引擎优化至少包括那几步?(开源ElasticsearchType类型Document可以分组吗?(一)(组图))
文章目录
前言一、基本概念全文搜索是最常见的需求,开源的Elasticsearch(以下简称Elastic)是目前全文搜索引擎的首选。它可以快速存储、搜索和分析海量数据。Wikipedia、Stack Overflow、Github 都使用它。底层 Elastic 是开源库 Lucene。但是,你不能直接使用Lucene,你必须自己编写代码来调用它的接口。Elastic 是 Lucene 的一个包,提供开箱即用的 REST API 操作接口。1. Node 节点和 Cluster 集群
Elastic 本质上是一个分布式数据库,允许多台服务器协同工作,每台服务器都可以运行多个 Elastic 实例。
单个 Elastic 实例称为节点。一组节点形成一个集群。
2. 索引索引
Elastic 索引所有字段并在处理后将它们写入倒排索引。查找数据时,直接查找索引。
因此,Elastic 数据管理的顶层单元称为 Index。它是单个数据库的同义词。每个索引(即数据库)的名称必须是小写的。
下面的命令可以查看当前节点的所有索引。
获取 /_mapping?pretty=true
3. 文档
索引中的单个记录称为文档。许多文档形成一个索引。
文档以 JSON 格式表示,以下是一个示例。
{
"user": "张三",
"title": "工程师",
"desc": "数据库管理"
}
同一个Index中的文档不要求结构(scheme)相同,但最好保持相同,有利于提高搜索效率。
4. 类型
可以对文档进行分组。例如,在天气指数中,它们可以按城市(北京和上海)或按气候(晴天和雨天)分组。这种分组称为Type,它是一个用于过滤Documents的虚拟逻辑分组。
不同的类型应该有相似的模式,例如,id 字段不能是一组中的字符串,而另一组中不能是数值。这是与关系数据库表的区别。具有完全不同属性的数据(例如产品和日志)应该存储为两个索引,而不是一个索引中的两种类型(尽管可以这样做)。
以下命令可以列出每个索引中收录的类型。(与上面的截图相同)
获取 /_mapping?pretty=true
按照计划,Elastic 6.x 版本只允许每个 Index 收录一个 Type,而 7.x 版本将彻底移除 Type。
5. 逻辑比较
上面提到的集群、节点、索引、类型、文档、分片(底层封装)和映射是什么?
如何区分和比较非关系型数据库elasticsearch和关系型数据库,elasticsearch是面向文档的
如下:关系型数据库和elasticsearch的客观对比!
关系型数据库 非关系型数据库
数据库数据库
指数
桌子
类型(版本 7 已完全弃用)
行
文档
字段列
场地
Elasticsearch(集群)可以收录多个索引(数据库),每个索引可以收录多个类型(表),每个类型收录多个文档(行),每个文档收录多个字段(列表)。
6. 物理设计
Elasticsearch在后台将每个索引分成多个shard,每个shard可以在集群中不同的服务器之间迁移。
集群的默认名称是 elasticsearch。
一个集群至少有一个节点,一个节点就是一个elasticsearch进程。一个节点可以有多个索引。默认情况下,如果创建索引,索引将由 5 个分片(primary shards,也称为主分片)组成。是的,每个主分片都会有一个副本(副本分片,也称为分配分片)
索引分为多个shard,每个shard就是一个Lucene索引,所以一个elasticsearch索引是由多个Lucene索引组成的。因为elasticsearch使用Lucene作为底层。
二、ES 命令风格
一种软件架构风格,而不是标准,它只是提供一组设计原则和约束,主要用于与客户端和服务器交互的软件。基于这种风格设计的软件可以更简洁、更有层次、更容易实现缓存等机制。
基本 RESTFUL 命令说明:
methodurl地址说明
放
本地主机:9200/index_name/type_name/document_id
创建文档(指定文档 ID)
邮政
本地主机:9200/index_name/type_name
创建文档(随机文档 ID)
邮政
本地主机:9200/index_name/type_name/document_id/_update
修改文档
删除
本地主机:9200/index_name/type_name/document_id
删除文件
得到
本地主机:9200/index_name/type_name/document_id
按文档id查询文档
邮政
本地主机:9200/index_name/type_name/document_id/_search
查询所有文件
PUT:一般创建索引,类型,文档 POST:添加数据,创建索引,类型,查询 DELETE:删除索引,文档 GET:查询 三、 创建和删除索引 index 创建索引索引
放置/天气
相当于
curl -X PUT 'localhost:9200/天气'
服务器返回一个带有确认字段的 JSON 对象,表明操作成功。
然后,发出删除请求以删除索引。
删除/天气
相当于
curl -X DELETE 'localhost:9200/天气'
四、Tokenizer 使用与学习
elasticsearch的查询是先通过tokenizer对单词进行分词,然后使用倒排索引匹配查询。
1. 理论研究
分词:就是将一段中文或者其他的一段分割成关键词,当我们搜索的时候,elasticsearch tokenizer会对自己的信息进行分词,对数据库或者索引库中的数据进行分词,然后执行一个匹配操作,默认的中文分词是将每个字符都当作一个词来对待,例如“我爱冯凡丽”会分为“我”、“爱”、“冯”、“凡”、“李”,这显然是不符合要求的,所以我们需要安装中文分词器ik来解决这个问题。
ES默认分词是英文分词,对中文分词不太支持。如果要使用中文,推荐使用ik tokenizer!所以我们需要安装ik中文分词。
IK提供了两种分词算法:ik_smart和ik_max_word,其中ik_mart是最小分词,ik_max_word是最新粒度分词!我们将在一段时间内测试!
安装在第一篇博客中已经介绍过了,传送门:elasticsearch学习一:理解ES,版本之间的对应关系。安装 elasticsearch、kibana、head 插件、elasticsearch-ik 分词器。
2. 用 kibana 测试
ik_mart 是最少细分的
ik_max_word 是最新的粒度划分,它穷尽了词库的可能性。
输入超喜欢冯安辰java
发现问题:风安辰被分开了,
你需要的这种词,你需要将它添加到我们的分词器的字典中!
ik tokenizer 添加了自己的配置!
ik分词器自定义配置,我写了一篇博客:elasticsearch学习之三:elasticsearch-ik分词器的自定义配置分词内容
设置好后再次执行:
以后需要自己配置的分词可以在自己定义的dic文件中配置!五、数据操作1. 创建索引 创建索引方法1,简单创建索引
PUT/索引名称创建索引方式2、创建索引并添加数据,字段类型系统默认给出
该方法会直接创建索引名称、类型、id,并添加数据。
PUT /索引名/~类型名~/文档id
{请求体}
*敏*感*词*
PUT /test1/type1/1
{
"name": "冯安晨",
"age": 18
}
这样,index、type、id创建完成后,就添加了一条数据。
创建索引方法3、创建索引并指定字段类型
创建索引,指定类型名称,指定字段类型
PUT /test2
{
"mappings": {
"type2": {
"properties": {
"name": {
"type": "text"
},
"age": {
"type": "long"
},
"birthday": {
"type": "date"
}
}
}
}
}
2. 字段类型摘要
那么上面的name字段就不需要指定类型了,毕竟我们的关系数据库需要指定类型!!
3. 查看规则信息
那就是看一下上面命令创建的细节
获取命令
GET /test1 : 查看索引信息
如果我们自己的文档字段没有指定,那么ES会给我们默认的配置字段类型!就是上面的test1索引,没有指定字段类型,所以ES默认指定类型。
4. 系统命令
通过elasticsearch命令查看ES的各种信息!通过
获取_猫/
获取大量关于ES的最新信息!
GET _cat/indices/?v:查看索引情况
其他命令。
5 添加数据
默认指定数据类型
PUT /fenganchen/user/1
{
"name": "冯凡利",
"age": 18,
"desc": "一顿操作猛如虎,一看工资2500",
"tags": ["技术宅", "温暖", "直男"]
}
6. 修改数据 PUT 修改(不推荐)
修改类似于add,但是这个修改类似于overwrite,如果缺少某个字段,则某个字段消失
查看 GET /fenganchen/user/1(如下所述)
修订
PUT /fenganchen/user/1
{
"name": "冯凡利123",
"age": 18,
"desc": "一顿操作猛如虎,一看工资2500",
"tags": ["技术宅", "温暖", "直男"]
}
_version 表示被修改的次数
查看确认
获取 /fenganchen/user/1
湾。_update 修改(推荐)修改
POST fenganchen/user/1/_update
{
"doc": {
"name": "冯凡利java"
}
}
2. 查看
7. 删除7. 简单查询 GET fenganchen/user/1
简单的条件查询
GET /fenganchen/user/_search?q=name:冯凡利 (报错,还未找到原因)
GET /fenganchen/user/_search?q=age:18
8.向复杂查询添加更多数据
PUT /fenganchen/user/2
{
"name": "张三",
"age": 17,
"desc": "法外狂徒张三",
"tags": ["技术宅", "温暖", "渣男"]
}
PUT /fenganchen/user/3
{
"name": "李四",
"age": 30,
"desc": "mmp 不知怎么形容了",
"tags": ["靓女", "旅游", "唱歌"]
}
查询关键字:查询
match关键字:match,这里有很多选项,比如:match_all:匹配所有,bool:返回一个布尔值,exists:存在等等。
GET fenganchen/user/_search
{
"query": {
"match": {
"name": "冯凡利"
}
}
}
3. 再添加一条数据,方便查询和测试:
PUT /fenganchen/user/4
{
"name": "冯凡利前端",
"age": 3,
"desc": "一顿操作猛如虎,一看工资2500",
"tags": ["技术宅", "温暖", "直男"]
}
再次查询:如下图
Hits:包括索引和文档信息、查询结果总数、查询到的具体文档
max_score:最大分数,是下面数据中最大的匹配分数值,也是最合适的
_score:可以用来判断谁更符合结果,每个数据都有这个属性
_source:数据对象信息关键字。
9 筛选结果
不想显示这么多字段,只想显示name和desc字段,可以使用数据对象信息关键字:_source来限制显示字段。
GET fenganchen/user/_search
{
"query": {
"match": {
"name": "冯凡利"
}
},
"_source": ["name", "desc"]
}
后面我们会用java来操作es,这里所有的方法和对象都是key:这个key也是hits、score等关键字。
10. 排序
GET fenganchen/user/_search
{
"query": {
"match": {
"name": "冯凡利"
}
},
"sort": [
{
"age": {
"order": "asc"
}
}
]
}
11.分页查询
GET fenganchen/user/_search
{
"query": {
"match": {
"name": "冯凡利"
}
},
"sort": [
{
"age": {
"order": "desc"
}
}
],
"from": 0,
"size": 1
}
from:从第一条数据开始
size:返回多少条数据(单页数据)
数据下标还是从 0 开始,和所有学过的数据结构一样!
/搜索/{当前}/{页面大小}
12. 布尔查询必须(and),必须满足所有条件,类似于:where id=1 and name=xxx
GET fengfanli/user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "冯凡利"
}
},
{
"match": {
"age": "18"
}
}
]
}
}
}
should(or),必须满足所有条件,类似于: where id=1 orname=xxx
GET fenganchen/user/_search
{
"query": {
"bool": {
"should": [
{
"match": {
"name": "冯凡利"
}
},
{
"match": {
"age": "18"
}
}
]
}
}
}
**must_not(not)**,必须满足所有条件,类似于: where id != 1
GET fenganchen/user/_search
{
"query": {
"bool": {
"must_not": [
{
"match": {
"age": 3
}
}
]
}
}
}
13.过滤常见匹配查询
任何收录风范里字符串的东西都会被找到
GET fenganchen/user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "冯凡利"
}
}
]
}
}
}
添加过滤器,过滤器
filter关键字过滤查询的数据。
GET fenganchen/user/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "冯凡利"
}
}
],
"filter": {
"range": {
"age": {
"gt": 3
}
}
}
}
}
}
上面的语句是对查询语句进行过滤,过滤掉年龄大于3的数据
14. 个空格匹配多个条件
匹配关键字空间
多个条件,以空格分隔
只要隐藏其中一个结果,就能查出
这时候通过_score分数就可以做出一个基本的判断了。
以下查询语句的含义:在tags字段中找到male和technical的数据并进行查询
GET fenganchen/user/_search
{
"query": {
"match": {
"tags": "男 技术"
}
}
}
15. 词条精确查询 i。术语分析
词条查询是通过倒排索引指定词条的过程直接搜索的!
关于分词:
ii. 两类文字关键词详解
分词器不能使用两种类型的文本关键字
文本类型:可分段
关键字类型:不能分段
首先创建索引并指定属性规则,如下:
一个。版本 6 创建索引并指定规则
elasticsearch 6.X必须指定创建索引的类型,feng_type是索引的类型名
```json
PUT testdb
{
"mappings": {
"feng_type": {
"properties": {
"name": {
"type": "text"
},
"desc": {
"type": "keyword"
}
}
}
}
}
```
湾。版本 7 创建索引并指定规则
elasticsearch 7.x 不需要指定类型来创建索引,因为版本7弃用了类型关键词(这里我就不演示了,我用的是6.4. 2 版本在这里。)
```json
PUT testdb
{
"mappings": {
"properties": {
"name": {
"type": "text"
},
"desc": {
"type": "keyword"
}
}
}
}
```
C。添加数据
```json
PUT testdb/feng_type/1
{
"name": "冯凡利java name",
"desc": "冯凡利java desc"
}
PUT testdb/feng_type/2
{
"name": "冯凡利java name",
"desc": "冯凡利java desc2"
}
```
添加文档 1
添加文档 2
d。elasticsearch-head的google插件,查看testdb索引数据
e. elasticsearch-head 的 Google 插件,参见 testdb 映射规则
索引情况,可以查看索引的设置详情,以及映射映射规则包括类型和属性。
可以看到,name 属性是 text 类型,而 desc 是关键字类型。
F。默认标记器测试:关键字
KeywordAnalyzer 将整个输入视为单个词汇单元,以促进特定类型文本的索引和检索。使用 关键词 标记器为邮政编码和地址等文本信息创建索引项非常方便。
使用默认的关键字tokenizer进行分词,(比如说ik tokenizer是中文tokenizer),这里可以看出没有分析
G。默认标记器测试:标准
英文的处理能力和StopAnalyzer一样,支持中文的方法是分词。它将词汇单元转换为小写并删除停用词和标点符号。
使用默认的标准分词器进行分词,见这里分析
H。term 准确查找文本类型
一世。term 查找确切的关键字类型
j. 总结 h 和 i 的检验
在 testdb 索引中:
名称字段是文本类型,
desc 字段是关键字类型。
但是,当 term 精确搜索它们时,它会发现:
在查找文本类型的名称字段时,只需收录它,即文本类型可以被分词器解释。在查找关键字类型的 desc 字段时,必须完全收录,即关键字类型将整个输入匹配为单个词法单元,由分词器解释。16. 多词精确匹配 a. 添加多数
PUT testdb/feng_type/3
{
"t1": "22",
"t2": "2020-4-6"
}
PUT testdb/feng_type/4
{
"t1": "33",
"t2": "2020-4-7"
}
湾。查看 elasticsearch-head 的谷歌插件,查看 testdb 索引数据和映射规则。索引数据
映射规则
C。词条精确查询
@>
17. Highlight 高亮关键字:highlight
GET fenganchen/user/_search
{
"query": {
"match": {
"name": "冯凡利"
}
},
"highlight": {
"fields": {
"name": {}
}
}
}
自定义搜索突出显示
GET fenganchen/user/_search
{
"query": {
"match": {
"name": "冯凡利"
}
},
"highlight": {
"pre_tags": "<p class='key style='color:red'>",
"post_tags": "",
"fields": {
"name": {}
}
}
}
</p>
这些mysql也可以做,但是mysql的效率比较低