Elasticsearch-7(全文搜索应用分享)

Elasticsearch-7(全文搜索应用分享)

官网doc
https://www.elastic.co/guide/en/elasticsearch/reference/7.5/index.html
官方php-api
https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html

1、概述

Elasticsearch 不仅仅只是全文搜索,还可以处理结构化搜索、数据分析、复杂的人类语言处理、地理位置和对象间关联关系等。

2、es 环境搭建

测试环境:
centos 7
elasticsearch 7.*
kibana 7.* //es管理端
jdk 1.8

2.1、Centos系统文件修改
1.修改文件描述符数量
因为elasticsearch对文件描述符的限制至少为65536,所以必须要修改系统的文件描述符数量
#sudo vi /etc/security/limits.conf
# 添加如下内容:
	* 	soft nofile 65536
	* 	hard nofile 65536
	* 	soft nproc 4096
	* 	hard nproc 4096
 
 2.修改 20-nproc.conf文件
#sudo vi /etc/security/limits.d/20-nproc.conf
# 修改 your_linux_user_name soft nproc 1024 为  
	* 	soft nproc 4096
 
 3.修改 max_map_count值
# sudo vi /etc/sysctl.conf
# 添加下面配置:
	vm.max_map_count=655360
 4.执行命令系统修改生效
 sysctl -p
 5.关闭SELinux (安全策略)
 Linux在安装好之后通常SELinux都是出于默认开启的状态,开启的情况下会导致一些服务的安装不成功。
 临时关闭
 #setenforce 0
 #getenforce //查看
 # vim /etc/selinux/config
 将SELINUX=enforcing改为SELINUX=disabled
2.2、安装 jdk1.8
https://www.linuxidc.com/Linux/2018-03/151326.htm
jdk-8u211-linux-x64.tar.gz

解压到/usr/local/jdk
#tar -zxvf jdk-8u211-linux-x64.tar.gz
cp jdk1.8.0_211 /usr/local/jdk1.8.0_211

#vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.8.0_211
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin
//配置生效
#source /etc/profile
//查看安装成否成功
#java -version
2.3.安装elasticsearch 7.*
> 使用yum 安装方法
1.添加elasticsearch 认证
# rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch

2.添加 elasticsearch 7.* 版本的yum源库
在 /etc/yum.repos.d 新建一个 elastic-7.repo源文件并添加es源
# vim /etc/yum.repos.d/elastic-7.repo
[elastic-7.x]
name=Elastic repository for 7.x packages
baseurl=https://artifacts.elastic.co/packages/7.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md

3.升级软件包
注意只升级软件包 不是升级软件库
#yum upgrade
4.升级完成后 就可以用 yum 安装es
如果不带版本号安装,则默认安装最新版本。这里我安装的是7.3版本
# yum install elasticsearch-7.3.0
5.查看安装
#whereis elasticsearch
[root@mlgz-test yum.repos.d]# whereis elasticsearch
elasticsearch: /etc/elasticsearch /usr/share/elasticsearch
说明:
》 /etc/elasticsearch 里面包含 elasticsearch的配置文件与插件的配置文件
》 /usr/share/elasticsearch 这里面是elasticsearch的源码文件:启动、管理

至此elasticsearch 7.3.0安装完成
2.4 elasticsearch 基本配置(单节点配置)
elasticsearch的配置文件
# cd /etc/elasticsearch/
analysis-ik      elasticsearch.keystore  elasticsearch.yml.20190517  log4j2.properties  roles.yml  users_roles
analysis-ik.bak  elasticsearch.yml       jvm.options                 role_mapping.yml   users
》其中 elasticsearch.yml就是配置文件
》修改文件前先备份,养成好的习惯。
# cp elasticsearch.yml elasticsearch.yml.bak
》1.修改elasticsearch.yml
# vim elasticsearch.yml
》主要修改配置如下:
cluster.name: mltest-es //es 集群名称
node.name: mltest-node-1 //集群中这个节点的名称
path.data: /data/es      //数据存放目录
path.logs: /var/log/elasticsearch //日志目录
network.host: 192.168.100.76  //主机ip
http.port: 9200    //访问端口http.port: 9200
discovery.seed_hosts: ["mlgz-test"] //显示主机名称
cluster.initial_master_nodes: ["mltest-node-1"] //集群中 配置哪个为主节点 与node.name 节点名一致
xpack.security.audit.enabled: true //启动es的安全插件,主要用来监听es,其他功能需要付费使用。

2.修改es使用内存 大于2G,一般设置为主机的 1/2内存大小
注意: Xms与Xmx要设置一样大小。
# vim jvm.options 
-Xms2g    //这里我设置为2G
-Xmx2g    //这里我设置为2G
》至些es的基本配置已完成
这里提一下es的配置说明:
es是分布式的,所有以节点为概念,一个elasticsearch服务就是启动一个节点。连接在一起的节点就称为集群
es天生就是为分布式来生的。内置一套集群节点管理,不用我们去做其它处理。
主动发现节点,主动监听连接的节点健康信息,数据负载等。
es的节点分为三种:
Master资格节点:控制集群的主节点。//配置node.master:true 单节点服务,不用配置,默认是开启node.master:true,node.data:true
数据节点:保存数据并执行数据相关操作:CRUD,搜索,聚合等 //配置node.data:true
客户端节点:只能响应用用户的请求,在所有连接的集群上分发执行搜索,处理路由请求,是一个智能的负载平衡器。//配置,当一个节点的node.master和node.data都设置为false的时,这个节点既不能保存数据与不能成功主节点。
》如果配置多个节点形成es集群。则在elasticsearch.yml配置中添加以下几项配置
node.master:true //配置这个节点为主节点
discovery.zen.minimum_master_nodes: 1,集群中最小数量的主资格节点的数量。 配置的公式(master_eligible_nodes / 2) + 1  
discovery.zen.ping.unicast.hosts: ["mltest-node-1", "mltest-node-2"]  //发现的节点名称
注意:discovery.zen.minimum_master_nodes
这个值是为了防止“脑裂”用的。
假设我们集群中的三个节点都可以被选为master(master-eligible),
但是由于一个节点由于网络问题,与其他两个节点无法通讯了,
那么此时集群划分为了2+1。
如果这个节点将自己选为了master,那么此时就会出现两个master,
也就是俗称的”脑裂“。那么为了防止这单独的节点不会将自己选为master,
就需要利用这个值。比如我们这里配置的是2,那么这个节点发现自己只有1个人,
就不会把自己选为master了,这样就避免了”脑裂“的情况。
通常这个值等于(master_eligible_nodes / 2) + 1。
在我们的例子中,就是(1 / 2) + 1 = 1。 因为只设置一个节点可以成为主节点资格。
2.5 安装es管理软件 kibana
1.安装
因为之前安装es时已添加了es的软件源所以所有es相关的软件都使用相同的源
#yum install kibana-7.3.0 //因为我们es安装的是es-7.3.0,所以对应的kibana是安装7.3.0
查看kibana安装文件
#whereis kibana
[root@mlgz-test elasticsearch]# whereis kibana
kibana: /etc/kibana /usr/share/kibana
2.配置
kibana的配置文件在/etc/kibana/kibana.yml
#cp kibana.yml kibana.yml.bak
#vim /etc/kibana/kibana.yml
server.port: 5601  //接入kibana的端口
server.host: 192.168.100.76 //接入kibana的ip
server.name: "mltest-kibana"  //kibana的服务名称
elasticsearch.hosts: ["http://192.168.100.76:9200"] //es主节点ip+端口
》说明:es与kibana安装完成后,把之前添加的es软件源先重命令名、备份。待以后使用。
#mv /etc/yum.repos.d/elastic-7.repo  /etc/yum.repos.d/elastic-7.repo.bak
因为当以后安装其他软件时如果使用 yum update 命令更新软件包时,也会把以安装的es7.3更新为当前最新版本的es。所有需要注意。
2.6 启动、重启、停用
#es
systemctl start elasticsearch
systmectl restart elasticsearch
systmectl stop elasticsearch

#kibana
systemctl start kibana
systemctl restart kibana
systemctl stop kibana

查看端口 tcp
netstat -lnt
查看进程
ps -ef|grep elasticsearch
ps -ef|grep kibana

打开kibana客户端
http://192.168.100.76:5601
2.7 查看es基本信息
GET /_cat/indices //查看es 所有索引库

每个索引库是由多个分片+多个副本组成,
节点中每个索引库的分片与副本是在不同节点中。

GET /_cat/shards?v  //查看es 所有分片信息

GET /_cat/count?v  //所有索引或单个索引返回的文档个数
GET /_cat/health?v //es集群健库度信息
GET /_cat/master?v //返回当选主节点信息
GET /_cat/nodes //返回集群拓扑相关信息

es节点中索引库的分片与副本存储分布情况
2.8 启用 kinana自带的数据监控

3.elasticsearch应用-全文本数据搜索

1.es与mysql对比
database(数据库)    index(索引库)
table(表)           type(类型)
row(行)             document(文档)
column(列)          field(字段)
注意:elasticsearch 7.0 以上版本已弱化了type(类型)的概念。在8.0版本中将去除type。


2.字段映射(msyql字段类型定义)
2.1.字段常用类型
字符型分为两种,
1)全文本(text)。通常用于文本的相关性搜索,全文本字段可以分词。
2)关键字(keyword)。长度256个字符 关键字是个精准值,通常用于过滤、排序、参与聚合,关键字不分词

数字型:long,integer,short,byte,double,float
日期型:date
布尔型:boolean
(注意在es中只有字符串类型才支持分词)
----------
#字符类型常用映射参数:
 analyzer:字段所使用的分析器,默认使用es的标准分析器:standard
 index:字段是否可以被用户搜索 默认:index:true
 search_analyzer:指定搜索时字段上使用的分析器
 --------
#日期类型常用映射参数:指定日期格式
注意:数字类型是不支持分词。
> format:"yyyy-MM-dd" 单日期格式
> format:"yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" 多日期格式
 不指定日期格式则用户写入什么日期则存储什么日期
 如:
  {
    "_source" : {
      "pid" : 2,
      "title" : "huangcheng",
      "date" : "2019-01-14"   //标准日期
    }
  },
  {
    "_source" : {
      "pid" : 3,
      "title" : "标题3",
      "date" : 1578987777  //时间戳
    }
}
--------
#数字类型常用映射参数

注意:数字类型是不支持分词。
coerce:字符串型数据转换为整数数字
ignore_malformed:是否忽略畸型数字
index:是否可以被用户搜索

2.2.常用的字段映射方式:自定义映射、动态映射

》自定义映射(自定义字段)
通常用的映射类型:text、keyword、date、long、integer、float、boolean
注意:
es 采用REST API 方式 语法:json格式
 GET //es 查询语句
 PUT //es 设置语句
 DELETE //es 删除语句
 POST //es 写入数据语句
字段映射操作方法: 
PUT /索引库/
{
    "mappings":{}
}
如:定义一名为test03库,并定义 pid,title,content,date 四个字段
PUT /test03/  #test03索引名称
{
     #默认 5个分片,1 个副本
      "settings" : {
          "number_of_shards" : 3,  #定义分片数
          "number_of_replicas" : 1 #定义副本数
       },
  "mappings": {
      "dynamic":false,//关闭自动添加字段功能
       "properties":{
        "pid":{
            "type":"long"
        },
        "title":{
            "type":"text",
            "fields":{
                "keyword":{
                  "type":"keyword"
                }
            }
        },
        "content":{
            "type":"text"
        },
        "date":{
             "type":"date"   
        }
    }
  }
}
-----
说明:
title 字段定义了一个多字段名为keyword类型为keyword
content:为什么没有定义一个keyword类型的字段
因为 keyword的特点是不分词,在搜索时如果要精准搜索标题就可以使用这个字段。
keyword类型的长度是:256个字符,title字段一般写入的字符不会太长。
而content字段保存文章的内容一般字符比较长。多定义一个keyword字段没有太大的意义。
注意虽然title定义了两个字段,但写入数据与显示时只使用到title名称
如果要精准查询title时
使用:title.keyword。
#查看
GET /test03/_mapping
返回:
{
  "test03" : {
    "mappings" : {
      "dynamic" : "false",
      "properties" : {
        "content" : {
          "type" : "text"
        },
        "date" : {
          "type" : "date"
        },
        "pid" : {
          "type" : "long"
        },
        "title" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword"
            }
          }
        }
      }
    }
  }
}


-----------
#写数据
POST /test03/_doc/1
{
  "pid":1,
  "title":"米奇的花园",
  "date":"2019-01-14"
}

#查看所有数据
GET /test03/_search
{
    "query":{
        "match_all":{}
    }
}
》至此一个基本的库与字段自定义的方式映射完成了。
接下来看一下动态映射
》动态映射(由es自动识别数据定义类型)
方法直接写入数据,
如:
#test02写入数据
POST /test02/_doc/1
{
  "uid":1,
  "name":"huangcheng"
}
---------------------
#查看test02 字段映射
GET /test02/_mapping
结果:
{
  "test02" : {
    "mappings" : {
      "properties" : {
        "name" : {
          "type" : "text",
          "fields" : {
            "keyword" : {
              "type" : "keyword",
              "ignore_above" : 256
            }
          }
        },
        "uid" : {
          "type" : "long"
        }
      }
    }
  }
}
es自动映射的text字段自动添加一个keyword字段,类型为keyword
-----------------------

4.es基本搜索应用

添加测试数据
POST /test03/_doc/1
{
  "pid":1,
  "title":"米奇的花园",
  "date":"2019-01-14"
}


POST /test03/_doc/2
{
  "pid":2,
  "title":"米老鼠的音乐会",
  "date":"2019-01-15"
}

POST /test03/_doc/3
{
  "pid":3,
  "title":"湖北大米",
  "date":"2019-01-15"
}

POST /test03/_doc/4
{
  "pid":4,
  "title":"北国雪花",
  "date":"2019-01-13"
}

POST /test03/_doc/5
{
  "pid":5,
  "title":"月季花",
  "date":"2019-01-13"
}
注意:在es中如果/_doc/ _id文档数值一样,则会覆盖原来的数据

搜索:
GET /test03/_search
{
  "query": {
    "match_all": {}
  }
}

GET /test03/_search
{
    "query":{
        "match":{
            "title":"大米"
        }
    }
}

GET /test03/_search
{
    "query":{
        "match":{
            "title":"北国"
        }
    }
}

》简单介绍 es的数据索引
名词:倒排索引
doc1:米奇的花园
doc2:北国雪花
doc3:月季花

1.分词
#查看 title字段的分词
GET /test03/_analyze
{
  "field": "title",
  "text":"米奇的花园"
}
米 
奇
的
花
园
北
国
雪
月
季

2.建立倒排索引
分词    doc1      doc2      doc3
米       1          0        0
奇       1          0        0
的       1          0        0
花       1          1        1
园       1          0        0
北       1          0        0
国       1          0        0
雪       1          0        0

通过分词并建立倒排索引可以看出两个问题
1、搜索“雪花”时,把其他带”花“的doc也搜索出来。
   这并不是用户想要的结果,精准度不够。
2、中文分词不友好。
   把每个中文的按单个字分词了,这样的话,如是是文章内容。
   (增加了索引词条的大小、增加了没有实际意义的引索词条,影响词条匹配的效率)
   
  》分词是elasticsearch 建立倒排索引的一个重要的依据。
  分词-》倒排索引-》搜索(词条匹配)。
  在映射test03索引库的字段时我们没有指定分析器,所有es使用的默认的分析器:standard
 standard分词器:基于Unicode文本分割算法。
 https://www.elastic.co/guide/en/elasticsearch/reference/7.5/analysis-standard-analyzer.html
  

4.2 IK中文分析器

IK可以按中文词组切分中文字符串。
如:月季花 =>月季、月季花、季花、月

》IK中文分析器插件安装
获取官网 IK 地址
https://github.com/medcl/elasticsearch-analysis-ik
https://github.com/medcl/elasticsearch-analysis-ik/releases 安装包
选择安装es对应的版本:
如图





1.安装ik 中文分析器插件命令
#/usr/share/elasticsearch/bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.3.0/elasticsearch-analysis-ik-7.3.0.zip
查看是否已完成好,可以查看/ect/elasticsearch/,
可以看到多了 ik 相关的文件夹 analysis-ik
[root@mlgz-test ~]# ls /etc/elasticsearch
analysis-ik      elasticsearch.keystore  elasticsearch.yml.20190517  log4j2.properties  roles.yml  users_roles
analysis-ik.bak  elasticsearch.yml       jvm.options                 role_mapping.yml   users
》在/etc/elasticsearch 目录的analysis-ik,就是ik分析器的配置文件。

2.ik分析器配置
》查看analysis-ik目录
extra_main.dic              extra_single_word_low_freq.dic  main.dic         sipa_main.dic      suffix.dic
extra_single_word.dic       extra_stopword.dic              preposition.dic  sipa_stopword.dic  surname.dic
extra_single_word_full.dic  IKAnalyzer.cfg.xml              quantifier.dic   stopword.dic 
》其中.dic是内置常用词典,IKAnalyzer.cfg.xml是配置文件
修改配置如下:
###start----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
        <comment>IK Analyzer 扩展配置</comment>
        <!--用户可以在这里配置自己的扩展字典 -->
        <entry key="ext_dict">main.dic;extra_main.dic;sipa_main.dic</entry>
         <!--用户可以在这里配置自己的扩展停止词字典-->
        <entry key="ext_stopwords">stopword.dic;extra_stopword.dic;sipa_stopword.dic</entry>
        <!--用户可以在这里配置远程扩展字典 -->
        <entry key="remote_ext_dict">http://192.168.100.76:9211/sipaDict.txt</entry>
        <!--用户可以在这里配置远程扩展停止词字典-->
        <entry key="remote_ext_stopwords">http://192.168.100.76:9211/sipaStopDict.txt</entry>
</properties>
###end----
》说明:
多个词典用分号隔开
配置远程词典的作用是:更新远程词典时可以不用重启es,远程字典扩展名用.txt(UTF-8,unix格式)
停止词:对词条进行过虑作用
扩展字典:对词条不分词
》利nginx访问远程字典
nginx.conf 添加如下配置
###start
server {
        listen 9211;
        server_name 192.168.100.76;
        location / {
                root /www/es_sipa_dict/;
        }
        error_page 404 /404.html;
            location = /40x.html {
        }
        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
}
###end
4.3 IK中文分析器的基本应用
》IK分析器有两种分词器(tokenizer)
ik_smart: 智能分词(词组)
ik_max_word:最大匹配分词算法(包含词组)
》测试 ik 两种分词器
1.重新映射字段
###start
PUT /test5/
{
 "settings" : {
      "number_of_shards" : 3, 
      "number_of_replicas" : 1
  },
  "mappings": {
      "dynamic":false,
       "properties":{
        "pid":{
            "type":"long"
        },
        "title":{
            "type":"text",
            "analyzer":"ik_max_word",
            "search_analyzer":"ik_max_word",
            "fields":{
                "keyword":{
                  "type":"keyword"
                }
            }
        },
        "content":{
            "type":"text",
            "analyzer":"ik_max_word",
            "search_analyzer":"ik_max_word"
        },
        "date":{
             "type":"date"   
        }
    }
  }
}
###end
》在text类型添加
"analyzer":"ik_max_word",  //建立索引时使用ik_max_word分词器
"serch_analyzer":"ik_max_word" //搜索时使用的ik_max_word分词器

##测试test5 ik分词器是否生效
GET /test5/_analyze
{
  "analyzer": "ik_max_word",
  "text":"米奇的花园"
}

GET /test5/_analyze
{
  "analyzer": "ik_smart",
  "text":"米奇的花园"
}
##测试title字段ik_max_word分词
GET /test5/_analyze
{
  "field": "title",
  "text":"米奇的花园"
}

》批量添加测试数据
POST /_bulk
{"create":{"_index":"test5","_id":1}}
{"pid":1,"title":"米奇的花园","date":"2019-01-13"}
{"create":{"_index":"test5","_id":2}}
{"pid":2,"title":"米老鼠的音乐会","date":"2019-01-14"}
{"create":{"_index":"test5","_id":3}}
{"pid":3,"title":"湖北大米","date":"2019-01-15"}
{"create":{"_index":"test5","_id":4}}
{"pid":4,"title":"北国雪花","date":"2019-01-13"}
### 删除所有数据
POST /test5/_delete_by_query
{
  "query": {
    "match_all": {}
  }  
}

####更新数据
POST /test5/_update/4
{"doc":{"title":"北国雪花"}}

4.4 分词器的过虑器
# 测试数据
POST /test5/_doc/5
{"pid":5,"title":"mickey liked garden AND dogs"}
POST /test5/_doc/6
{"pid":6,"title":"参观F1比赛"}
POST /test5/_doc/7
{"pid":7,"title":"参观一级方程式比赛"}
#搜索
GET test5/_search
{
  "query": {
    "match": {
      "title":"like"
    }
  }
}


》在ES中一个Analyzer 由下面三种组件组合而成:
character filter :字符过滤器,对文本进行字符过滤处理,如处理文本中的html标签字符。
处理完后再交给tokenizer进行分词。一个analyzer中可包含0个或多个字符过滤器,多个按配置顺序依次进行处理。
tokenizer:分词器,对文本进行分词。一个analyzer必需且只可包含一个tokenizer。
token filter:词项过滤器,对tokenizer分出的词进行过滤处理。如转小写、停用词处理、同义词处理。

1.自定义中文分词器理:中文分词,转小写,停用词处理、同义词处理
PUT /test1
{
  "settings":{
    "number_of_shards" : 5, 
    "number_of_replicas" : 1,
    "analysis":{   #定义分析器
      "analyzer":{   #定义分词器
        "ik_syno":{  #ik_syno:自定义的分词器名称
          "type":"custom",    
          "tokenizer":"ik_max_word",   
         #指定哪些过虑器:lowercase:转小写,stemmer:词干提取,my_synonym_filter:自定义的过虑器
          "filter":["lowercase","stemmer","my_synonym_filter"]  
        },
        "ik_syno_smart":{
          "type":"custom",
          "tokenizer":"ik_smart",
          
          "filter":["lowercase","stemmer","my_synonym_filter"]
        }
      },
      "filter":{ #//定义一个同义过虑器
        "my_synonym_filter":{   #//自定义的过虑器名称
          "type":"synonym",     #过虑器类型 同义词
          #//同义词词典路径: /etc/elasticsearch/
          "synonyms_path": "analysis-ik/synonym.txt"  
        }
      }
    }
  }
}
###end
》新建一个同义词字典否则,自定义分析器会报没有找到synonym.txt文件
#echo "" >/etc/elasticsearch/analysis-ik/synonym.txt
》同义词字典有两种写法
1、替换法:
    土豆>马铃薯
    马铃薯>土豆
2、同义法:
    F1、一级方程式
    海南、南海、海南省
    
》测试自定义的分析器是否有效
GET test1/_analyze
{
  "analyzer": "ik_syno",
  "text":"dogs"
}
GET test1/_analyze
{
  "analyzer": "ik_syno_smart",
  "text":"参观F1比赛"
}


2.映射字段
###start
PUT test1/_mapping
{

  "dynamic":false,
     "properties":{
      "pid":{
          "type":"long"
      },
      "title":{
          "type":"text",
          "analyzer":"ik_syno",
          "search_analyzer":"ik_syno",
          "fields":{
              "keyword":{
                "type":"keyword"
              }
          }
      },
      "content":{
          "type":"text",
          "analyzer":"ik_syno",
          "search_analyzer":"ik_syno"
      },
      "date":{
           "type":"date"   
      }
  }
}
###end
》查看字段
GET test1/_mapping
》测试字段分析器是否有效
GET test1/_analyze
{
  "field": "title",
  "text": "参观F1比赛"
}

》添加测试数据
###start
POST /_bulk
{"create":{"_index":"test1","_id":1}}
{"pid":1,"title":"米奇的花园 mickey liked garden AND dogs","date":"2019-01-13"}
{"create":{"_index":"test1","_id":2}}
{"pid":2,"title":"参观F1比赛","date":"2019-01-14"}
{"create":{"_index":"test1","_id":3}}
{"pid":3,"title":"参观一级方程式比赛","date":"2019-01-15"}
{"create":{"_index":"test1","_id":4}}
{"pid":4,"title":"北国雪花","date":"2019-01-13"}
###end
》查看数据
GET /test1/_search
{
  "query": {"match_all": {}}
}
》F1,花、like、dog
GET test1/_search
{
  "query": {
    "match":{
      "title":"一级方程式"
    }
  }
}
》至此 基本就可以支持中英的 "全文搜索引擎”基本搭建完成,接下来查查
elasticsearch常用的查询使用

5.elasticsearch常用的查询使用

5.1.term词条查询
》term(词条查询)的特点是不分词查询 精准查询
GET test1/_search
{
    "query":{
        "term":{
            "title":"北国雪花"
        }
    }
}
》上面的查询不到数据,因为在es没有"北国雪花"这个索引词条。
GET test1/_search
{
    "query":{
        "term":{
            "title.keyword":"北国雪花"
        }
    }
}

POST test1/_doc/5
{"pid":5,"title":"月季花"}

GET test1/_search
{
    "query":{
        "term":{
            "title":"月季花"
        }
    }
}

GET /test1/_analyze
{
  "text": "月季花",
  "analyzer": "ik_syno_smart"
}
5.2.多词条查询(terms)
多词条查询允许匹配那些在内容中含有某些词条的文档。词条查询允许匹配单个未经分析的
词条,多词条查询可以用来匹配多个这样的词条

GET test1/_search
{
    "query":{
        "terms":{
            "title":["北国雪花","月季花"]
        }
    }
}
GET test1/_search
{
    "query":{
        "terms":{
            "pid":["1","2","3"]
            
        }
    }
}
GET test1/_search
{
    "query":{
        "terms":{
            "date":["2019-01-13"]
            
        }
    }
}
5.3.match_all查询
match_all 查询是Elasticsearch中最简单的查询之一。它使我们能够匹配索引中的所有文件
GET /test1/_search
{
  "query": {"match_all": {}}
}

GET /sipa_photo/_search
{
  "query": {
    "match_all": {}
  },
  
  "size":20,
  "from": 2, 
  "sort": [
    {
      "photoid": {"order": "desc"},
      "moddate": {"order":"asc"}
    }
  ],
  
  "_source": ["title","photoid","ifmod","moddate"]
  
}
5.4.match查询
match 查询把 query 参数中的值拿出来,加以分析,然后构建相应的查询。使用 match 查询
时,Elasticsearch将对一个字段选择合适的分析器,所以可以确定,传给 match 查询的词条将被建
立索引时相同的分析器处理。
GET test1/_search
{
  "query": {
    "match":{
      "title":{
        "query": "like dog 南海",
        "operator": "and"
      }
    }
  }
}

GET sipa_photo/_search
{
  "query": {
    "match":{
      "title":{
        "query": "黑龙江 森林公园", 
        "operator": "and",
        "cutoff_frequency": 0.001,
        "zero_terms_query":"none",
        "minimum_should_match": "75%"
      }
    }
  }
}

与term精确查询不同,对于match查询,只要被查询字段中存在任何一个词项被匹配,就会搜索到该文档。
operator :此参数可以接受 or 和 and ,控制用来连接创建的布尔条件的布尔运算符。默
认值是 or 。如果希望查询中的所有条件都匹配,可以使用 and 运算符。
cutoff_frequency:该参数允许将查询分解成两组:一组低频词和一组高频词,
cutoff_frequency 配置有两种形式
指定为一个分数( 0.01 )表示出现频率
指定为一个正整数( 5 )则表示出现次数
这种方式已在最新版本弃用,建意:match prhase
 zero_terms_query :该参数允许指定当所有的词条都被分析器移除时(例如,因为停
止词),查询的行为。它可以被设置为 none 或 all ,默认值是 none 。在分析器移除所有查
询词条时,该参数设置为 none ,将没有文档返回;设置为 all ,则将返回所有文档
minimum_should_match:表示字段匹配的数量
minimum_should_match配置有两种形式
指定为一个分数( 70% )表示出现频率
指定为一个正整数( 2 )则表示出现次数,表示分词必须匹配查询条件的数量为2。即分词在有两个相同的
minimum_should_match 属性值,默认值是1,如果设置其值为2,表示分词必须匹配查询条件的数量为2
5.5.multi_match查询
匹配多个字段
GET sipa_photo/_search
{
  "query": {
    "multi_match":{
      "query": "景山公园"
      , "fields": ["title","gtitle"]
      ,"operator": "and",
        "minimum_should_match": "75%"
    }
  },
    "_source": ["title","photoid","ifmod","moddate"]
}
5.7.match_phrase:短语匹配,近似匹配
和match查询类似,match_phrase查询首先解析查询字符串来产生一个词条列表。然后会搜索所有的词条,但只保留包含了所有搜索词条的文档,并且词条的位置要邻接。
就是将多个term作为一个短语


{
"query":{
    "mathc_phrase" :{
        "title" :{
            "query":"crime and punishment",
            "slop":"1"                    -- 一个整数值,构建短语时,中间允许的未知词条数。默认为0
            "analyzer":""                 -- 分析时用到的分析器
        }
    }
}
}

GET sipa_photo/_search
{
  "query": {
    "match_phrase": {
      "title":"景山公园"
    }
  }
}
5.8.复合查询:bool、constant_score
1.constant_score:精确值查询,表示查询以非评分模式进行,这样可以省掉评分过程,提高查询速度
constant_score 查询封装了另一个查询(或过滤),并为每一个所封装查询(或过滤)返
回的文档返回一个常量得分。它允许我们严格控制与一个查询或过滤匹配
常用的过滤器包含 term 、 terms 、 range
GET sipa_photo/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term":{
          "syspid":24696809
        }
      }
    }
  }
}
GET sipa_photo/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term":{
          "upip":"60.181.137.129"
        }
      }
    }
  }
}
GET sipa_photo/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term":{
          "syspid":24696809
        }
      }
    }
  }
}

2.bool
通过布尔查询来封装无限数量的查询
should:查询可能被匹配,也可能不被匹配。被匹配的 should 节点数目
由 minimum_should_match 参数控制。
 minimum_should_match :此参数的值描述了文档被视为匹配时,应该匹配的 should
子句的最少数量。举例来说,它可以是个整数值,比如2,也可以是个百分比,比如75%。
must:查询必须匹配
must_not:查询必须不被匹配

####查询字段不为空
{
  "query": {
    "bool": {
      "must": {
        "exists": {
          "field": "字段名"
        }
      }
    }
  }
}
注意:而exists只能过滤掉为 null 的字段,其中不包括“”或“null”,
如果要过滤空的字符串应使用filter
##查询city不为空
GET sipa_photo/_search
{
  "query": {
    "bool": {
      "must_not": [
        {
          "bool": {
            "filter": {
              "term": {
                "city": " "
              }
            },
            "must": [
              {
                "exists": {
                  "field": "city"
                }
              }
            ]
          }
          
        }
      ]
    }
  }
}
#####
must 该条款(查询)必须出现在匹配的文件,并将有助于得分。
filter 子句(查询)必须出现在匹配的文档中。然而不像 must查询的分数将被忽略。Filter子句在过滤器上下文中执行,这意味着评分被忽略,子句被考虑用于高速缓存。

should 子句(查询)应该出现在匹配的文档中。如果 bool查询位于查询上下文中并且具有mustorfilter子句,那么bool即使没有 should查询匹配,文档也将匹配查询。在这种情况下,这些条款仅用于影响分数。如果bool查询是过滤器上下文 或者两者都不存在,must或者filter至少有一个should查询必须与文档相匹配才能与bool查询匹配。这种行为可以通过设置minimum_should_match参数来显式控制 。

must_not 子句(查询)不能出现在匹配的文档中。子句在过滤器上下文中执行,意味着评分被忽略,子句被考虑用于高速缓存。因为计分被忽略,0所有文件的分数被返回。

即,must:必须匹配,filter:匹配的结果过滤,should:至少有一个 must_not:不能匹配

且:匹配关键词   gtitle字段必须出现在匹配的文件,并增加得分值”


GET /sipa_photo/_search
{
	"query": {
		"bool": {
		  "must": [
		    {
		      "query_string": {
		        "default_field": "gtitle",
		        "query": "火神山"
		      }
		    }
		  ], 
		 
		    "should": [
        {
           "multi_match":{
            "query": "火神山"
            , "fields": ["title","gtitle","gcontent","keyword"]
         
            ,"operator": "and",
            "minimum_should_match": "70%"
          }
        }
      ],
				"minimum_should_match": 1,
			"filter": [
				[{
					"term": {
						"pindex": "1"
					}
				}, {
					"term": {
						"ifmod": "1"
					}
				}]
			]
		}
	},
	"_source": ["title","keyword","gtitle"]
	,
	"size": "30",
	"from": 0,
	"sort": [{
		"moddate": {
			"order": "desc"
		}
	}]
}


#####
#查询多个字段中有"景山公园",并且“keyword":有”万春亭“,
#按 photoid:排序
#过虑 ifmod = 1 
#过虑 时间: 1557572447 - 1569941452
#过虑 photoid: 22905029 - 23724282
#过虑 pfcate :GNXW
#过虑 pindex:1

GET sipa_photo/_search
{
  "query": {
    "bool": {
      
      "should": [
        {
           "multi_match":{
            "query": "景山公园"
            , "fields": ["title","gtitle","gcontent"]
            ,"operator": "and",
              "minimum_should_match": "75%"
          }
        }
      ],
      
      "must": [
        {
          "match": {
            "keyword":{
              "query": "万春亭",
              "minimum_should_match":"75%"
            }
          }
        }
      ],
      
      "filter": [
        [
          {
            "range":{
              "moddate":{
                "from":1557572447,
                "to":1569941452
              }
            }
            
          },
          {
            "range":{
              "photoid":{
                "from":22905029,
                "to":23724282
                
              }
            }
          }
        ],
        
        [
          {
            "terms":{
              "pfcate.keyword":["GNXW"]
            }
          },
          {
            "term":{
              "pindex":1
            }
          }
        ]
        
      ]
      
    }
  },
  
  
  "sort": [
    {
      "photoid": {
        "order": "desc"
      }
    }
  ], 
  "_source": ["photoid","pfcate","pindex","title","moddate","keyword"]
  ,"size":100
}
### bool复合查询2  ####
{
	"query": {
		"bool": {
			"should": [{
				"match_phrase": {
					"title": "景山公园"
				}
			}, {
				"match_phrase": {
					"gtitle": "景山公园"
				}
			}, {
				"match_phrase": {
					"keyword": "景山公园"
				}
			}, {
				"match_phrase": {
					"gcontent": "景山公园"
				}
			}],
			"minimum_should_match": 1,
			"filter": [
				[{
					"term": {
						"ifmod": "1"
					}
				}]
			]
		}
	},
	"size": "30",
	"from": 0,
	"sort": [{
		"moddate": {
			"order": "desc"
		}
	}]
}
5.9.超过 1万条数据显示
初始搜索请求应该在查询中指定 scroll 参数,这可以告诉 Elasticsearch 需要保持搜索的上下文环境多久,如 ?scroll=1m。1m表示 接收1分钟内的scroll请求。

GET sipa_photo/_search?scroll=1m
{
  "query": {
    "multi_match":{
      "query": "景山公园"
      , "fields": ["title","gtitle","gcontent"]
      ,"operator": "or",
        "minimum_should_match": "75%"
    }
  },
  
  "_source": ["title","photoid","ifmod","moddate"]
}

POST /_search/scroll
{
  "scroll":"1m",
  "scroll_id":"DXF1ZXJ5QW5kRmV0Y2gBAAAAAAAAmRcWOVNRaE1sQXNUdjJ4TU9Rc0dpQzdpQQ=="
}

POST 可以使用
URL不应该包含 index 或者 type 名字——这些都指定在了原始的 search 请求中。
scroll 参数告诉 Elasticsearch 保持搜索的上下文等待另一个 1m
scroll_id 参数

后续
elasticsearch 集群的管理
集群节点监控、水平扩展、节点分片管理、搜索路由选择、数据恢复、分片转移等等
elasticsearch 近实时大日志分析
数据采集(filebast、logstash)、实时分析、显示统计

常用查询语句

多字段查询bool+should+ multi_match用法
multi_match的type有三个 best_fields,most_fields,cross_fields。
其中best_fields,most_fields是以字段为中心的
cross_fields是以词条为中心的

查询关键词 “北京市 交通” 分别对应索引文档中的 title, keyword字段。
title6,keyword4的配置
multi_match中默认的type是:best_fields
“type”:“cross_fields”
如果使用best_fields,most_fields,不出意外应该是先将title字段中包含“北京市”的文档先检索出来。
如果使用cross_fields,会将title字段中包含“北京市”,keyword字段中包含“交通”的文档检索出来。
cross_fields把几个相关字段合并成了一个大字段,进行词频统计,当我们搜索多字段多关键词时,明显这种处理更符合我们的需求。

GET /sipa_photo/_search
{
	"query": {
		"bool": {
		  "must": [ //这里的must意思是查询的数据必须在gtitle中有匹配到关键词
		    {  
		      "query_string": {
		        "default_field": "gtitle",
		        "query": "武汉"
		      }
		    }
		  ], 
		 
		    "should": [
        {
           "multi_match":{
            "query": "武汉"
            , "fields": ["title^3","gtitle^5","gcontent^2","keyword^4"]
            //title^3 :这个意思是给字段加权重大小依次查询
            ,"operator": "and",  //还有 or ,一般or比较好。
            //and 表示 title,gtitle,gcontent,keyword这四个字段必须匹配到关键词
            "minimum_should_match": "70%"
          }
        }
      ],
				"minimum_should_match": 1,
			"filter": [
				[{
					"term": {
						"pindex": "1"
					}
				}, {
					"term": {
						"ifmod": "1"
					}
				}]
			]
		}
	},
	"_source": ["title","keyword","gtitle"]
	,
	"size": "30",
	"from": 0,
	"sort": [{
		"moddate": {
			"order": "desc"
		}
	}]
}

.多字段查询二 bool+should+match用法,可以给每一个字段定义不同的查询参数
并指定boost(类似权重,是提升文档搜索评分的重要因素)的大小,还根据不同的字段的数据类型指定不同的分词器analyzer,并指定分词的搜索方式operator

GET /sipa_photo/_search
{
  "bool" : {
    "should" : [
      {
        "match" : {
          "titleA" : {
            "query" : "北京交通",
            "operator" : "OR",
            "prefix_length" : 0,
            "max_expansions" : 50,
            "fuzzy_transpositions" : true,
            "lenient" : false,
            "zero_terms_query" : "NONE",
            "auto_generate_synonyms_phrase_query" : true,
            "boost" : 6.0
          }
        }
      },
      {
        "match" : {
          "titleB" : {
           "query" : "北京交通",
            "operator" : "OR",
            "prefix_length" : 0,
            "max_expansions" : 50,
            "fuzzy_transpositions" : true,
            "lenient" : false,
            "zero_terms_query" : "NONE",
            "auto_generate_synonyms_phrase_query" : true,
            "boost" : 5.0
          }
        }
      },
      {
        "match" : {
          "titleC" : {
             "query" : "北京交通",
            "operator" : "OR",
            "prefix_length" : 0,
            "max_expansions" : 50,
            "fuzzy_transpositions" : true,
            "lenient" : false,
            "zero_terms_query" : "NONE",
            "auto_generate_synonyms_phrase_query" : true,
            "boost" : 4.0
          }
        }
      },
      {
        "match" : {
          "gtitle" : {
             "query" : "北京交通",
            "operator" : "AND",
            "analyzer" : "ik_smart",
            "prefix_length" : 0,
            "max_expansions" : 50,
            "fuzzy_transpositions" : true,
            "lenient" : false,
            "zero_terms_query" : "NONE",
            "auto_generate_synonyms_phrase_query" : true,
            "boost" : 3.0
          }
        }
      },
      {
        "match" : {
          "keyword" : {
            "query" : "北京交通",
            "operator" : "OR",
            "analyzer" : "ik_smart",
            "prefix_length" : 0,
            "max_expansions" : 50,
            "fuzzy_transpositions" : true,
            "lenient" : false,
            "zero_terms_query" : "NONE",
            "auto_generate_synonyms_phrase_query" : true,
            "boost" : 2.0
          }
        }
      },
      {
        "match" : {
          "gcontent" : {
            "query" : "北京交通",
            "operator" : "OR",
            "prefix_length" : 0,
            "max_expansions" : 50,
            "fuzzy_transpositions" : true,
            "lenient" : false,
            "zero_terms_query" : "NONE",
            "auto_generate_synonyms_phrase_query" : true,
            "boost" : 1.0
          }
        }
      }
    ],
    "adjust_pure_negative" : true,
    "boost" : 1.0
  }
}
写法二
{
  "multi_match" : {
    "query" : "北京交通",
    "fields" : [
      "titleA^6.0",    //^相当于boost关键词
      "gtitle^1.0",
      "keyword^2.0",
      "content^4.0",
      "gcontent^3.0",
      "titlec^5.0"
    ],
    "type" : "best_fields",
    "operator" : "OR",
    "slop" : 0,
    "prefix_length" : 0,
    "max_expansions" : 50,
    "zero_terms_query" : "NONE",
    "auto_generate_synonyms_phrase_query" : true,
    "fuzzy_transpositions" : true,
    "boost" : 1.0
  }
}
分词后影响查询结果的两个参数minimum_should_match和operator
operator参数表示字段如何匹配分词后的搜索词 :and,or
operator这个对搜索精确度影响很大。
minium_should_match参数表示字段匹配关键词的数量最小限制,可以是数字字符串,也可以是百分比。
minium_should_match:"75%"
minium_should_match:1

查询语句

GET /sipa_photo/_search
{
	"query": {
		"bool": {
			"should": {
				"multi_match": {
					"query": "北京交通",
					"fields": ["title", "gtitle^5", "gcontent", "keyword^4"],
					"operator": "or",
					"minimum_should_match": "75%",
					"type":"cross_fields",
					"analyzer":"ik_syno"
					
				}
			},
			"minimum_should_match": 1,
			"must": [
			  {
			    "match":{
			      "gtitle":{
			         "query":"北京交通",
			         "operator": "or", 
			         "analyzer": "ik_syno"
			      }
			    }
			  },
			   {
			    "match":{
			      "keyword":{
			         "query":"北京交通",
			         "operator": "or", 
			         "analyzer": "ik_syno"
			      }
			    }
			  }
			], 
		 
			"filter": [
				[
				 {
					"term": {
						"pindex": "1"
					}
				}, {
					"term": {
						"ifmod": "1"
					}
				}]
			]
		}
	},
	"size": "500",
	"from": 0,
	"_source": ["title","keyword","gtitle","groupid","moddate"],
   "sort": [{
		"moddate": {
			"order": "desc"
		}
	}]
}

GET /sipa_photo/_search
{
	"query": {
		"bool": {
			"should": {
				"multi_match": {
					"query": "北京交通",
					"fields": ["title", "gtitle^5", "gcontent","keyword"],
					"operator": "and",
					"minimum_should_match": "75%"
				}
			},
			"minimum_should_match": 1,
	    "must": [
			  {
			    "match":{
			      "gtitle":{
			         "query":"北京交通",
			         "operator": "or", 
			         "analyzer": "ik_syno"
			      }
			    }
			  }
			],
			"filter": [
				[
				 {
					"term": {
						"pindex": "1"
					}
				}, {
					"term": {
						"ifmod": "1"
					}
				}]
			]
		}
	},
	"size": "500",
	"from": 0,
	"_source": ["title","keyword","gtitle","groupid","moddate"],
  "sort": [{
		"moddate": {
			"order": "desc"
		}
	}]
}

GET /sipa_photo/_analyze
{
  "analyzer": "ik_syno_smart",
  "text": "北京 交通"
}


GET /sipa_photo/_search
{
	"query": {
		"bool": {
			"should": {
				"multi_match": {
					"query": "社区量体温",
					"fields": ["title", "gtitle^5", "gcontent", "keyword^4"],
					"operator": "or",
					"minimum_should_match": "75%",
					"type":"best_fields",
					"analyzer":"ik_syno"
					
				}
			},
			"minimum_should_match": 1,
			"must": [
			  {
			    "match":{
			      "gtitle":{
			         "query":"社区量体温",
			         "operator": "or",
			         "analyzer":"ik_syno"
			      }
			    }
			  },
			   {
			    "match":{
			      "keyword":{
			         "query":"社区量体温",
			         "operator": "or", 
			         "analyzer": "ik_syno"
			      }
			    }
			  }
			], 
		 
			"filter": [
				[
				  {
					"term": {
						"ifmod": "1"
					}
				}]
			]
		}
	},
	"size": "500",
	"from": 0,
	"_source": ["title","keyword","gtitle","groupid","moddate"],
   "sort": [{
		"moddate": {
			"order": "desc"
		}
	}]
}

GET /sipa_photo/_search
{
	"query": {
		"bool": {
			"should": {
				"multi_match": {
					"query": "社区量体温",
					"fields": ["title", "gtitle", "gcontent", "keyword"],
					"operator": "and",
					"minimum_should_match": "70%"
				}
			},
			"minimum_should_match": 1,
			"must": [{
				"match": {
					"gtitle": "社区量体温"
				}
			}],
			"filter": [
				[{
					"term": {
						"ifmod": "1"
					}
				}]
			]
		}
	},
	"size": "30",
	"from": 0,
	"sort": [{
		"moddate": {
			"order": "desc"
		}
	}]
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值