1. 搜索引擎基础1

elasticsearch

简介

	Elasticsearch是一个基于Apache Lucene(TM)的开源搜索引擎。
无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。
	Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,
但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文搜索变得简单

elasticsearch除了Lucene和全文搜索,我们还可以描述它:
    1.分布式的实时文件存储,每个字段都被索引并可被搜索
    2.分布式的实时分析搜索引擎
    3.可以扩展到上百台服务器,处理PB级结构化或非结构化数据。

1.必须提前安装Java环境

[root@cs ~]# yum install java-1.8.0-openjdk.x86_64 -y
[root@cs ~]# java -version

2.安装

官网地址: https://www.elastic.co/cn/

elasticsearch,kibana,filebeat 必须保持相关软件版本一致

# 安装环境
centos7.9 + elasticsearch-6.8.15

# 下载
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.8.15.rpm

# 安装,使用yum安装和rpm命令安装都行
# yum install elasticsearch-6.8.15.rpm -y
rpm -ivh elasticsearch-6.8.15.rpm

# 运行
systemctl enable elasticsearch.service    # 加入开机启动
# 运行/停止运行/重启/状态
systemctl start/stop/restart/status elasticsearch.service 
systemctl is-active elasticsearch.service  # 确认es服务是否还活着

# 检查是否启动成功
curl localhost:9200

3.相关文件查看

# rpm -ql elasticsearch
[root@cs tmp]# rpm -qc elasticsearch
/etc/elasticsearch/elasticsearch.yml             # es配置文件
/etc/elasticsearch/jvm.options                   # java虚拟机的配置文件
/etc/elasticsearch/log4j2.properties             # es的日志使用的log4j的框架,所以有log4j的配置
/etc/elasticsearch/role_mapping.yml
/etc/elasticsearch/roles.yml
/etc/elasticsearch/users
/etc/elasticsearch/users_roles
/etc/init.d/elasticsearch                        # init.d启动脚本
/etc/sysconfig/elasticsearch                     # 一些环境变量,一般不用更改
/usr/lib/sysctl.d/elasticsearch.conf             # 环境变量相关            
/usr/lib/systemd/system/elasticsearch.service    # systemd启动脚本

/var/log/elasticsearch/elasticsearch.log		# es的日志文件
/usr/share/elasticsearch/						# es的安装目录
/usr/share/elasticsearch/bin/elasticsearch-plugin  # es用来下载插件的
/usr/share/elasticsearch/plugins/				# es的插件目录

4.修改配置文件

# 手动创建个es的数据目录
[root@cs tmp]# mkdir -p /data/elasticsearch_data
[root@cs tmp]# chown -R elasticsearch:elasticsearch /data/elasticsearch_data/
[root@cs tmp]# vim /etc/elasticsearch/elasticsearch.yml

# 更改后的配置文件内容如下
[root@cs tmp]# grep "^[a-Z]" /etc/elasticsearch/elasticsearch.yml 
node.name: node-1
# 保存数据和日志的目录
path.data: /data/elasticsearch_data
path.logs: /var/log/elasticsearch
bootstrap.memory_lock: true # 锁定内存
# 监听本机的ip,多个ip逗号间隔
network.host: 192.168.189.128,127.0.0.1 

# 完事重启服务
[root@cs tmp]# systemctl restart elasticsearch
# 然后观察日志,你会发现,有报错:
[root@cs tmp]# tail -f /var/log/elasticsearch/elasticsearch.log 
'''
[1]: memory locking requested for elasticsearch process but memory is not locked
'''

# 报错意思是锁定内存失败,参考官网的解决办法:
[root@cs tmp]# sudo systemctl edit elasticsearch

# 添加下面两行代码
[Service]
LimitMEMLOCK=infinity

[root@cs tmp]# sudo systemctl daemon-reload
[root@cs tmp]# systemctl restart elasticsearch

5.安装es-head 插件-- 小型可视化工具

chrome的应用商店打不开的话,去这个地址

谷歌浏览器添加扩展插件

引擎可视化工具 - kibana安装

1.安装

# 在安装kibana之前,请确保java环境和elasticsearch都已配置并启动成功。
# 安装环境:
	elasticsearch-6.8.15 + kibana-6.8.15 + centos7.9

# 下载安装
[root@cs tmp]# wget https://artifacts.elastic.co/downloads/kibana/kibana-6.8.15-x86_64.rpm
[root@cs tmp]# rpm -ivh kibana-6.8.15-x86_64.rpm

# 启动/状态/重启/停止/加入开机自启/取消开机自启
[root@cs tmp]# systemctl start/status/restart/stop/enable/disable kibana

2.相关目录

/etc/kibana/kibana.yml        # kibana配置文件
/usr/share/kibana             # kibana安装目录

3.修改配置文件

[root@cs tmp]# vim /etc/kibana/kibana.yml 
[root@cs tmp]# grep "^[a-Z]" /etc/kibana/kibana.yml 
# 监听的ip和端口
server.port: 5601
server.host: "192.168.189.128"  
server.name: "10.0.0.200-kibana"                      # kibana的服务名
elasticsearch.hosts: ["http://192.168.189.128:9200"]       # 访问指定es的hosts

# 重启
[root@cs tmp]# systemctl restart kibana

使用kibana操作es

1.简单操作 -- 增删改查

# 创建一篇文档 -- 索引/映射类型/文档id
# 首先检查索引是否存在,不存在先创建索引,再创建文档
PUT zhifou/doc/1
{
  "name":"顾老二",
  "age":30,
  "from": "gu",
  "desc": "皮肤黑、武器长、性格直",
  "tags": ["黑", "长", "直"]
}

# 删除指定文档
DELETE zhifou/doc/4

# 删除指定索引
DELETE /zhifou

 # doc里指定要修改的字段和内容
POST zhifou/doc/1/_update
{
  "doc": { # doc里指定
    "desc": "皮肤很黄",
    "tags": ["很黄","很长", "很直"]
  }
}

# 1.查询所有索引
GET _cat/indices?v

# 2.查询指定索引内容
GET zhifou/_search
GET zhifou/doc/_search # 指定类型

# 3.查询指定文档内容
GET zhifou/doc/1

2.复杂查询

1.准备数据

PUT zhifou/doc/1
{
  "name":"顾老二",
  "age":30,
  "from": "gu",
  "desc": "皮肤黑、武器长、性格直",
  "tags": ["黑", "长", "直"]
}

PUT zhifou/doc/2
{
  "name":"大娘子",
  "age":18,
  "from":"sheng",
  "desc":"肤白貌美,娇憨可爱",
  "tags":["白", "富","美"]
}

PUT zhifou/doc/3
{
  "name":"龙套偏房",
  "age":22,
  "from":"gu",
  "desc":"mmp,没怎么看,不知道怎么形容",
  "tags":["造数据", "真","难"]
}


PUT zhifou/doc/4
{
  "name":"石头",
  "age":29,
  "from":"gu",
  "desc":"粗中有细,狐假虎威",
  "tags":["粗", "大","猛"]
}

PUT zhifou/doc/5
{
  "name":"魏行首",
  "age":25,
  "from":"广云台",
  "desc":"仿佛兮若轻云之蔽月,飘飘兮若流风之回雪,mmp,最后竟然没有嫁给顾老二!",
  "tags":["闭月","羞花"]
}

2.两种查询方式

字符串查询 -- 不推荐使用

# q后边是查询条件
GET zhifou/doc/_search?q=age:18
GET zhifou/_search?q=age:18

结构化查询 - match查询

# 1.match:返回所有匹配的分词。
    # 查询条件是一步步构建出来的,将查询条件添加到match中即可,对查询条件进行分词
    GET zhifou/doc/_search
    {
      "query": {
        "match": {
          "from": "gu"
        }
      }
    }
    
# 2.match_all:查询全部。
# match_all的值为空,表示没有查询条件,那就是查询全部
    GET zhifou/doc/_search
    {
      "query": {
        "match_all": {}
      }
    }
    
# 3.match系列之match_phrase(短语查询)
# 使用match的话,中文会被分成一个一个的字,构不成短语查询,没有意义
    GET zhifou/doc/_search
    {
      "query": {
        "match_phrase": {
        # 字段 : 想要查询的短语
          "desc": "仿佛"
        }
      }
    }
    
# 4.match系列之match_phrase_prefix(最左前缀查询)
# 当你记不住想要查询的完整单词,可以写最前边的几个字母进行查询
    GET zhifou/_search
    {
      "query": {
        "match_phrase_prefix": {
        # 查询来自前缀为sh的文档
          "from": "sh"
        }
      }
    }
    
# 5.match系列之multi_match(多字段查询)
# 适用多个字段查询一样的条件
    GET t3/doc/_search
    {
      "query": {
        "multi_match": {
          "query": "beautiful", # 查询条件
          "fields": ["title", "desc"] # 查询字段
        }
      }
    }
# 5.1 multi_match甚至可以当做match_phrase和match_phrase_prefix使用,只需要指定type类型即可
	# 最左前缀查询
    GET t3/doc/_search
    {
      "query": {
        "multi_match": {
          "query": "gi",
          "fields": ["title"],
          "type": "phrase_prefix"
        }
      }
    }
    # 短语查询
    GET t3/doc/_search
    {
      "query": {
        "multi_match": {
          "query": "girl",
          "fields": ["title"],
          "type": "phrase"
        }
      }
    }

3.排序查询 -- sort

# 升序:asc -- 降序:desc
# 比如我们查询顾府都有哪些人,并根据age字段按照升序降序排列
GET zhifou/doc/_search
{
  "query": {
    "match": {
      "from": "gu"
    }
  },
  "sort": [
    {# 排序字段
      "age": {
        "order": "asc" # 升序
      }
    }
  ]
}

4.分页查询 - from/size

# from:从哪开始查 -- size:查几个
    GET zhifou/doc/_search
    {
      "from": 0,
      "size": 2
    }
    

5.布尔查询 -- bool

must:与关系,相当于关系型数据库中的and。
should:或关系,相当于关系型数据库中的or。
must_not:非关系,相当于关系型数据库中的not。
filter:过滤条件。
    -range:条件筛选范围。
        gt:大于,相当于关系型数据库中的>。
        gte:大于等于,相当于关系型数据库中的>=。
        lt:小于,相当于关系型数据库中的<。
        lte:小于等于,相当于关系型数据库中的<=。

基本操作

# 1.must 与 -- 查询from=gu和age=30的文档
    GET zhifou/_search
    {
      "query": {
        "bool": {
        # 查询关系类型,是个列表里放查询条件
          "must": [
            {
              "match": {
                "from": "gu"
              }
            },
            {
              "match": {
                "age": "30"
              }
            }
          ]
        }
      }
    }
    
# 2.should 或 -- 查询只要是from为gu或者tags为闭月的数据
    GET zhifou/doc/_search
    {
      "query": {
        "bool": {
          "should": [
            {
              "match": {
                "from": "gu"
              }
            },
            {
              "match": {
                "tags": "闭月"
              }
            }
          ]
        }
      }
    }
    
# 3. must_not 非 -- 想要查询from既不是gu并且tags也不是可爱,还有age不是18的数据
    GET zhifou/doc/_search
    {
      "query": {
        "bool": {
          "must_not": [
            {
              "match": {
                "from": "gu"
              }
            },
            {
              "match": {
                "tags": "可爱"
              }
            },
            {
              "match": {
                "age": 18
              }
            }
          ]
        }
      }
    }
    
# 4. filter 过滤查询 -- 要查询from为gu,age大于25的数据
# filter最好与must一起使用,因为查询过程中,优先经过filter过滤,如果是should的话,结果会不准确
    GET zhifou/doc/_search
    {
      "query": {
        "bool": {
          "must": [
            {"match": {
              "from": "gu"
            }}
          ], 
          "filter": {
            "range": {
            # 过滤字段
              "age": {
              # 过滤范围
                "gt": 25
              }
            }
          }
        }
      }
    }

6.结果过滤:_source

# 在所有的结果中,我只需要查看name和age两个属性,其他的不要怎么办
    GET zhifou/_search
    {
      "query": {
        "match": {
          "from": "gu"
        }
      }, 
      # 把我们想要看到的数据放到列表中
      "_source": ["name","age"]
    }

7.高亮查询 :highlight -- 查询条件在结果中高亮显示

# 1.默认高亮显示
    GET zhifou/_search
    {
      "query": {
        "match_phrase": {
          "name": "石头"
        }
      }, 
      "highlight": {
        "fields": {
        # 需要高亮显示查询条件的字段
          "name": {},
          "tags": {}
        }
      }
    }

# 2.自定义样式高亮显示
    GET zhifou/chengyuan/_search
    {
      "query": {
        "match": {
          "from": "gu"
        }
      },
      "highlight": {
        # 开始标签 -- 可以写样式
        "pre_tags": "<b style='color:red'>",
        # 结束标签
        "post_tags": "</b>",
        "fields": {
          "from": {}
        }
      }
    }

8.聚合函数 - 分组查询: aggs

注意:聚合函数的使用,一定是先查出结果,然后对结果使用聚合函数做处理
avg:求平均
max:最大值
min:最小值
sum:求和
分组查询

基本操作:

# 1.avg -- 查询from是gu的人的平均年龄
    GET zhifou/doc/_search
    {
      "query": {
        "match": {
          "from": "gu"
        }
      },
      "aggs": {
      	# 自定义函数别名
        "pingjun": {
        # 聚合函数类型 -- 可以替换成其他类型
          "avg": {
          # 字段
            "field": "age"
          }
        }
      },
      # 不想看查询数据,只想看聚合函数值
      "size": 0
    }

# 2.分组查询 
# 想要查询所有人的年龄段,并且按照15~20,20~25,25~30分组,并且算出每组的平均年龄
    GET zhifou/doc/_search
    {
      "size": 0, 
      "query": {
        "match_all": {}
      },
      # 分组
      "aggs": {
       # 分组别名
        "age_group": {
        # 分组
          "range": {
          # 想要分组字段
            "field": "age",
            # 分组范围列表
            "ranges": [
              {
                "from": 15,
                "to": 20
              },
              {
                "from": 20,
                "to": 25
              },
              {
                "from": 25,
                "to": 30
              }
            ]
          },
          # 平均值
          "aggs": {
            "my_avg": {
              "avg": {
                "field": "age"
              }
            }
          }
        }
      }
    }

3.自定义索引结构: mappings 映射

1.mappings三种映射,具体由dynamic属性控制

  • 动态映射: dynamic:true -- 默认模式
  • 静态映射: dynamic:false
  • 严格模式: dynamic:strict
动态映射
# 定义了两个字段类型,当添加新字段sex时,也可以使用新字段进行数据查询
# 因为elasticsearch已经为新增的sex建立了映射关系
PUT m1
{
  "mappings": {
    "doc":{
      "dynamic":true,   # 默认动态可不写
      "properties": {
        "name": {
          "type": "text"
        },
        "age": {
          "type": "long"
        }
      }
    }
  }
}

静态映射
# 定义了两个字段类型,可以添加新字段sex时,但是使用新字段查询不到数据
# 因为elasticsearch并没有为新增的sex建立映射关系
PUT m2
{
  "mappings": {
    "doc":{
      "dynamic":false,   
      "properties": {
        "name": {
          "type": "text"
        },
        "age": {
          "type": "long"
        }
      }
    }
  }
}

严格模式
# 定义了两个字段类型,添加新字段,报错,只能添加已经定义的字段数据
PUT m3
{
  "mappings": {
    "doc": {
      "dynamic": "strict", 
      "properties": {
        "name": {
          "type": "text"
        },
        "age": {
          "type": "long"
        }
      }
    }
  }
}

小结:

  • 动态映射(dynamic:true):动态添加新的字段(或缺省)。
  • 静态映射(dynamic:false):忽略新的字段。在原有的映射基础上,当有新的字段时,不会主动的添加新的映射关系,只作为查询结果出现。
  • 严格模式(dynamic: strict):如果遇到新的字段,就抛出异常。

2.index -- 定义是否字段创建索引

首先来创建一个mappings

PUT m4
{
  "mappings": {
    "doc": {
      "dynamic": false,
      "properties": {
        "name": {
          "type": "text",
          "index": true
        },
        "age": {
          "type": "long",
          "index": false
        }
      }
    }
  }
}

3.settings 设置主 - 复制分片

在创建一个索引的时候,我们可以在settings中指定分片信息

PUT s1
{
  "mappings": {
    "doc": {
      "properties": {
        "name": {
          "type": "text"
        }
      }
    }
  }, 
  "settings": {
    "number_of_replicas": 1,
    "number_of_shards": 5
  }
}

# number_of_shards是主分片数量(每个索引默认5个主分片)
# number_of_replicas是复制分片,默认一个主分片搭配一个复制分片

原文地址:https://www.cnblogs.com/jia-shu/p/14805459.html