ElasticSearch(待改)

本文档详细介绍了全文检索基础、Elasticsearch的核心概念、安装步骤、客户端操作,包括索引、类型、字段、映射等,并对比了Elasticsearch与Solr的区别。此外,还介绍了IK分词器的安装与测试,以及使用Kibana进行DSL语句操作,展示了数据查询、分页、排序、高亮等实用技巧。最后,通过编程实例展示了如何在Java中操作Elasticsearch,包括创建索引、映射和文档,以及各种查询方式。
摘要由CSDN通过智能技术生成

感谢你的路过,希望学生的笔记能给你一点微不足道的参考
Java基础思维导图,完整Java体系的链接

这部分我不是很满意,感觉差一点什么。以后要重新来一次。
1,给的资料里部分方法是过时的
2,不够透彻,通融。不知道怎么写博客,先把资料放在这里。

目录标题

⼀、全⽂检索基础

1.1什么是全⽂检索

将⾮结构化数据中的⼀部分信息提取出来,重新组织,使其变得有⼀定结构,然后对此有⼀定结构的数
据进⾏搜索,从⽽达到搜索相对较快的⽬的。

1.2.全⽂检索流程

在这里插入图片描述

1.3相关概念

(1)索引库
索引库就是存储索引的保存在磁盘上的⼀系列的⽂件。⾥⾯存储了建⽴好的索引信息以及⽂档对象。 ⼀个索引库相当于数据库中的⼀张表。
在这里插入图片描述
(2) document对象
获取原始内容的⽬的是为了索引,在索引前需要将原始内容创建成⽂档(Document),⽂档中包括⼀
个⼀个的域(Field),域中存储内容。每个⽂档都有⼀个唯⼀的编号,就是⽂档id。document对象相当于表中的⼀条记录。
在这里插入图片描述
(3)field对象
如果我们把document看做是数据库中⼀条记录的话,field相当于是记录中的字段。field是索引库中存
储数据的最⼩单位。field的数据类型⼤致可以分为数值类型和⽂本类型,⼀般需要查询的字段都是⽂本
类型的,field的还有如下属性:
   是否分词:是否对域的内容进⾏分词处理。前提是我们要对域的内容进⾏查询。
   是否索引:将Field分析后的词或整个Field值进⾏索引,只有索引⽅可搜索到。
      ⽐如:商品名称、商品简介分析后进⾏索引,订单号、⾝份证号不⽤分词但也要索引,这些将来都
要作为查询条件。
   是否存储:将Field值存储在⽂档中,存储在⽂档中的Field才可以从Document中获取
      ⽐如:商品名称、订单号,凡是将来要从Document中获取的Field都要存储。
(4) term对象
从⽂档对象中拆分出来的每个单词叫做⼀个Term,不同的域中拆分出来的相同的单词是不同的
term。term中包含两部分⼀部分是⽂档的域名,另⼀部分是单词的内容。term是创建索引的关键词
对象。

⼆、ElasticSearch简介

2.1 什么是ElasticSearch

⼀个开源的⾼扩展的分布式全⽂检索引擎,它可以近乎实时的存储、检索数据。

2.2ElasticSearch对⽐Solr

Solr 利⽤ Zookeeper 进⾏分布式管理,⽽ Elasticsearch ⾃⾝带有分布式协调管理功能;
Solr ⽀持更多格式的数据,⽽ Elasticsearch 仅⽀持json⽂件格式;
Solr 官⽅提供的功能更多,⽽ Elasticsearch 本⾝更注重于核⼼功能,⾼级功能多有第三⽅插件提供;
Solr 在传统的搜索应⽤中表现好于 Elasticsearch,但在处理实时搜索应⽤时效率明显低于Elasticsearch.

三、ElasticSearch相关概念(术语)

3.1 概述

Elasticsearch是⾯向⽂档(document oriented)的,它可以存储整个对象或⽂档(document)。不仅仅是存储,还会索引(index)每个⽂档的内容使之可以被搜索。在Elasticsearch中,可以对⽂档(⽽⾮成⾏成列的数据)进⾏索引、搜索、排序、过滤。Elasticsearch⽐传统关系型数据库如下:
在这里插入图片描述

3.2 Elasticsearch核⼼概念

3.2.1 索引 index

⼀个索引就是⼀个拥有⼏分相似特征的⽂档的集合。可以理解成⼀个关系型数据库

3.2.2 类型 type

⼀个索引中,你可以定义⼀种或多种类型。⼀个类型是你的索引的⼀个逻辑上的分类/分区,其语义
完全由你来定。⼀种type就像⼀类表.

3.2.3 字段Field

相当于是数据表的字段,对⽂档数据根据不同属性进⾏的分类标识.

3.2.4 映射 mapping

mapping是处理数据的⽅式和规则⽅⾯做⼀些限制,如某个字段的数据类型、默认值、分析器、是否被
索引等等。相当于关系型数据库中的表结构。

3.2.5 ⽂档 document

⼀个⽂档是⼀个可被索引的基础信息单元,相当于关系型数据库中的⼀⾏记录。

3.2.6 接近实时 NRT

Elasticsearch是⼀个接近实时的搜索平台。

3.2.7 集群 cluster

⼀个集群就是由⼀个或多个节点组织在⼀起,它们共同持有整个的数据,并⼀起提供索引和搜索功能。

3.2.8 节点 node

⼀个节点是集群中的⼀个服务器,作为集群的⼀部分,它存储数据,参与集群的索引和搜索功能。

3.2.9 分⽚和复制

Elasticsearch提供了将索引划分成多份的能⼒,这些份就叫做分⽚。当你创建⼀个索引的时候,你
可以指定你想要的分⽚的数量。每个分⽚本⾝也是⼀个功能完善并且独⽴的“索引”,这个“索引”可以被
放置到集群中的任何节点上。分⽚很重要,主要有两⽅⾯的原因:
(1)允许你⽔平分割/扩展你的内容容量。
(2)允许你在分⽚(潜在地,位于多个节点上)之上进⾏分布式的、并⾏的操作,进⽽提⾼性能/吞吐

Elasticsearch允许你创建分⽚的⼀份或多份拷贝,这些拷贝叫做复制分⽚,或者直接叫复制。
复制之所以重要,有两个主要原因:
(1)在分⽚/节点失败的情况下,提供了⾼可⽤性。
(2)扩展你的搜索量/吞吐量.

四、Elasticsearch 安装

本章节将采⽤Docker安装,由于windows安装es⾮常简单,这⾥不再重复.这里建议用虚拟机。

4.1docker镜像下载

docker pull elasticsearch:5.6.8

4.2安装es容器

docker run -di --name=kkb_es -p 9200:9200 -p 9300:9300 elasticsearch:5.6.8

9200端⼜(Web管理平台端⼜) 9300(服务默认端⼜)
浏览器输⼊地址访问:http://192.168.211.132:9200/
在这里插入图片描述

4.3开启远程连接

上⾯完成安装后,es并不能正常使⽤,elasticsearch从5版本以后默认不开启远程连接,程序直接连接会
报如下错误
在这里插入图片描述
我们需要修改es配置开启远程连接,代码如下:
登录容器

docker exec -it kkb_es /bin/bash

查看⽬录结构 输⼊: dir

root@07f22eb41bb5:/usr/share/elasticsearch# dir
NOTICE.txt README.textile bin config data lib logs modules plugins

进⼊config⽬录

cd config

查看⽂件

root@07f22eb41bb5:/usr/share/elasticsearch/config# ls
elasticsearch.yml log4j2.properties scripts

修改elasticsearch.yml⽂件

root@07f22eb41bb5:/usr/share/elasticsearch/config# vi elasticsearch.yml
bash: vi: command not found

vi命令⽆法识别,因为docker容器⾥⾯没有该命令,我们可以安装该编辑器。
设置apt下载源

docker cp ~/sources.list kkb_es:/etc/apt/sources.list

安装vim编辑器

apt-get update
apt-get install vim

安装好了后,修改elasticsearch.yml配置,如下图:

vi elasticsearch.yml

同时添加下⾯⼀⾏代码:

cluster.name: my-elasticsearch

重启docker

docker restart kkb_es

4.4跨域配置

修改elasticsearch/config下的配置⽂件:elasticsearch.yml,增加以下三句命令,并重启:

http.cors.enabled: true
http.cors.allow-origin: "*"
network.host: 192.168.220.100

在这里插入图片描述
其中:
http.cors.enabled: true:此步为允许elasticsearch跨域访问,默认是false。
http.cors.allow-origin: “”:表⽰跨域访问允许的域名地址(表⽰任意)。
network.host: 宿主机IP
重启

 docker restart kkb_es

⼩提⽰:如果想让容器开机重启,可以执⾏下⾯命令

docker update --restart=always 容器名称或者容器id

4.5系统参数配置

重启后发现重启启动失败了,这时什么原因呢?这与我们刚才修改的配置有关,因为elasticsearch在启
动的时候会进⾏⼀些检查,⽐如最多打开的⽂件的个数以及虚拟内存区域数量等等,如果你放开了此配
置,意味着需要打开更多的⽂件以及虚拟内存,所以我们还需要系统调优
修改vi /etc/security/limits.conf ,追加内容 (nofile是单个进程允许打开的最⼤⽂件个数 soft nofile 是
软限制 hard nofile是硬限制 )追加到最后。

* soft nofile 65536
* hard nofile 65536

修改vi /etc/sysctl.conf,追加内容 (限制⼀个进程可以拥有的VMA(虚拟内存区域)的数量 )

vm.max_map_count=655360

执⾏下⾯命令 修改内核参数马上⽣效

sysctl -p

重新启动虚拟机,再次启动容器,发现已经可以启动并远程访问

reboot

五、ElasticSearch的客户端操作

实际开发中,主要有三种⽅式可以作为elasticsearch服务的客户端:
   第⼀种,elasticsearch-head插件
   第⼆种,使⽤elasticsearch提供的Restful接⼜直接访问
   第三种,使⽤elasticsearch提供的API进⾏访问

5.1 elasticsearch-head

ElasticSearch不同于Solr⾃带图形化界⾯,我们可以通过安装ElasticSearch的head插件,完成图形化界
⾯的效果,完成索引数据的查看。安装插件的⽅式有两种,在线安装和本地安装。本⽂档采⽤本地安装
⽅式进⾏head插件的安装。elasticsearch-5-*以上版本安装head需要安装node和grunt
(1)下载head插件:https://github.com/mobz/elasticsearch-head
(2)将elasticsearch-head-master压缩包解压到任意⽬录,但是要和elasticsearch的安装⽬录区别开
(3)下载nodejs:https://nodejs.org/en/download/
这个略
(4)将grunt安装为全局命令 ,Grunt是基于Node.js的项⽬构建⼯具。进入elasticsearch-head-master,cmd,控制台中输⼊如下执⾏命令:

npm install -g grunt-cli

(5)进⼊elasticsearch-head-master⽬录启动head,在命令提⽰符下输⼊命令:

>npm install
>grunt server

(6)打开浏览器,输⼊ http://localhost:9100,看到如下页⾯:
在这里插入图片描述

5.2 使⽤Postman⼯具进⾏Restful接⼜访问

5.2.1 ElasticSearch的接⼜语法

curl -X<VERB> '<PROTOCOL>://<HOST>:<PORT>/<PATH>?<QUERY_STRING>' -d '<BODY>'

在这里插入图片描述

5.2.2 创建索引index和映射mapping

请求url:

PUT 192.168.220.100:9200/blog1

请求体:

{
 "mappings": {
 "article": {
 "properties": {
 "id": {
 "type": "long",
 "store": true,
 "index":"not_analyzed"
 },
 "title": {
 "type": "text",
 "store": true,
 "index":"analyzed",
 "analyzer":"standard"
 },
 "content": {
 "type": "text",
 "store": true,
 "index":"analyzed",
 "analyzer":"standard"
 }
 }
 }
 }
}

post man 截图:
在这里插入图片描述
elasticsearch-head查看:
在这里插入图片描述

5.2.3 创建索引后设置Mapping

我们可以在创建索引时设置mapping信息,当然也可以先创建索引然后再设置mapping。
在上⼀个步骤中不设置maping信息,直接使⽤put⽅法创建⼀个索引,然后设置mapping信息。
请求的url:

POST http://192.168.220.100:9200/blog2/hello/_mapping

请求体:

{
 "hello": {
 "properties": {
 "id":{
 "type":"long",
 "store":true
 },
 "title":{
 "type":"text",
 "store":true,
 "index":true,
 "analyzer":"standard"
 },
 "content":{
 "type":"text",
 "store":true,
 "index":true,
 "analyzer":"standard"
 }
 }
 }
 }

PostMan截图
在这里插入图片描述

5.2.4 删除索引index

请求url:

DELETE 192.168.220.100:9200/blog1

postman截图:
在这里插入图片描述

5.2.5 创建⽂档document

请求url:
POST 192.168.220.100:9200/blog1/article/1
请求体:

{
 "id":1,
 "title":"ElasticSearch是⼀个基于Lucene的搜索服务器",
 "content":"它提供了⼀个分布式多⽤户能⼒的全⽂搜索引擎,基于RESTful web接⼝。
Elasticsearch是⽤Java开发的,并作为Apache许可条款下的开放源码发布,是当前流⾏的企业级搜
索引擎。设计⽤于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使⽤⽅便。"
}

postman截图:
在这里插入图片描述
elasticsearch-head查看:
在这里插入图片描述

5.2.6 修改⽂档document

请求url:

POST 192.168.220.100:9200/blog1/article/1

请求体:

{
 "id":1,
 "title":"【修改】ElasticSearch是⼀个基于Lucene的搜索服务器",
 "content":"【修改】它提供了⼀个分布式多⽤户能⼒的全⽂搜索引擎,基于RESTful web接⼝。
Elasticsearch是⽤Java开发的,并作为Apache许可条款下的开放源码发布,是当前流⾏的企业级搜
索引擎。设计⽤于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使⽤⽅便。"
}

postman截图:
在这里插入图片描述
elasticsearch-head查看:
在这里插入图片描述

5.2.7 删除⽂档document

请求url:

DELETE 192.168.220.100:9200/blog1/article/1

postman截图:

在这里插入图片描述
elasticsearch-head查看:
在这里插入图片描述

5.2.8 查询⽂档-根据id查询

请求url:

GET 192.168.220.100:9200/blog1/article/1

postman截图:
在这里插入图片描述

5.2.9 查询⽂档-querystring查询

请求url:

POST 192.168.220.100:9200/blog1/article/_search

请求体:

{
 "query": {
 "query_string": {
 "default_field": "title",
 "query": "搜索服务器"
 }
 }
}

postman截图:
在这里插入图片描述
注意:
将搜索内容"搜索服务器"修改为"钢索",同样也能搜索到⽂档,该原因会在下⾯讲解中得到答案

{
 "query": {
 "query_string": {
 "default_field": "title",
 "query": "钢索"
 }
 }
}

钢索 -> “钢”, “索”,搜索是分成两个词,注意Standard标准分词器,会把汉字每个字⼀个词
存到索引库中的tilte,也是按照Standard进⾏的分词
所以搜索钢索能搜到这个document

5.2.10 查询⽂档-term查询

请求url:

POST 192.168.220.100:9200/blog1/article/_search

请求体:

{
 "query": {
 "term": {
 "title": "搜索"
 }
 }
}

postman截图:
在这里插入图片描述

六、IK分词器

6.1 IK分词器简介

IKAnalyzer是⼀个开源的,基于java语⾔开发的轻量级的中⽂分词⼯具包。从2006年12⽉推出1.0版开
始,IKAnalyzer已经推出 了3个⼤版本。最初,它是以开源项⽬Lucene为应⽤主体的,结合词典分词和
⽂法分析算法的中⽂分词组件。新版本的IKAnalyzer3.0则发展为 ⾯向Java的公⽤分词组件,独⽴于
Lucene项⽬,同时提供了对Lucene的默认优化实现。
IK分词器3.0的特性如下:
(1)采⽤了特有的“正向迭代最细粒度切分算法“,具有60万字/秒的⾼速处理能⼒。
(2)采⽤了多⼦处理器分析模式,⽀持:英⽂字母(IP地址、Email、URL)、数字(⽇期,常⽤中⽂数
量词,罗马数字,科学计数法),中⽂词汇(姓名、地名处理)等分词处理。
(3)对中英联合⽀持不是很好,在这⽅⾯的处理⽐较⿇烦.需再做⼀次查询,同时是⽀持个⼈词条的优化的词
典存储,更⼩的内存占⽤。
(4)⽀持⽤户词典扩展定义。
(5)针对Lucene全⽂检索优化的查询分析器IKQueryParser;采⽤歧义分析算法优化查询关键字的搜索排列组合,能极⼤的提⾼Lucene检索的命中率。

6.2 IK分词器安装

(1)安装ik分词器
IK分词器下载地址https://github.com/medcl/elasticsearch-analysis-ik/releases
将ik分词器上传到服务器上,然后解压,并改名字为ik

unzip elasticsearch-analysis-ik-5.6.8.zip
mv elasticsearch ik

将ik⽬录拷贝到docker容器的plugins⽬录下

docker cp ./ik kkb_es:/usr/share/elasticsearch/plugins

重启服务
(2)IK分词器测试
访问:http://192.168.211.132:9200/_analyze?analyzer=ik_smart&pretty=true&text=我是
程序员
访问:http://192.168.211.132:9200/_analyze?analyzer=ik_max_word&pretty=true&text=
我是程序员
ik_max_word:会将⽂本做最细粒度的拆分
    ⽐如会将“中华⼈民共和国⼈民⼤会堂”拆分为“中华⼈民共和国、中华⼈民、中华、华⼈、⼈民共
和国、⼈民、共和国、⼤会堂、⼤会、会堂等词语。
ik_smart:会做最粗粒度的拆分
    ⽐如会将“中华⼈民共和国⼈民⼤会堂”拆分为中华⼈民共和国、⼈民⼤会堂。

七、Kibana使⽤-掌握DSL语句

我们上⾯使⽤的是elasticsearch-head插件实现数据查找的,但是elasticsearch-head的功能⽐较单⼀,我们这⾥需要⼀个更专业的⼯具实现对⽇志的实时分析,也就是我们接下来要讲的kibana。
Kibana 是⼀款开源的数据分析和可视化平台,它是 Elastic Stack 成员之⼀,设计⽤于和 Elasticsearch
协作。您可以使⽤ Kibana 对 Elasticsearch 索引中的数据进⾏搜索、查看、交互操作。您可以很⽅便的
利⽤图表、表格及地图对数据进⾏多元化的分析和呈现。
Kibana 可以使⼤数据通俗易懂。它很简单,基于浏览器的界⾯便于您快速创建和分享动态数据仪表板
来追踪 Elasticsearch 的实时数据变化。
搭建 Kibana ⾮常简单。您可以分分钟完成 Kibana 的安装并开始探索 Elasticsearch 的索引数据 — 没有
代码、不需要额外的基础设施。

7.1 Kibana下载安装

我们项⽬中不再使⽤linux,直接使⽤Docker,所有这⾥就不演⽰在windows的下载安装了。
(1)镜像下载

docker pull docker.io/kibana:5.6.8

(2)安装kibana容器
执⾏如下命令,开始安装kibana容器

docker run -it -d -e ELASTICSEARCH_URL=http://192.168.220.100:9200 --name
kibana -p 5601:5601 kibana:5.6.8

ELASTICSEARCH_URL=http://192.168.220.100:9200:是指链接的ES地址
restart=always:每次服务都会重启,也就是开启启动
5601:5601:端⼜号

快捷键
ctrl+i ⾃动缩进
ctrl+enter 提交请求
down 打开⾃动补全菜单
enter或tab 选中项⾃动补全
esc 关闭补全菜单

(3)访问测试
访问http://192.168.220.100:5601如下:

7.2 Kibana使⽤

7.2.1 配置索引

要使⽤Kibana,您必须⾄少配置⼀个索引。索引⽤于标识Elasticsearch索引以运⾏搜索和分析。它们还
⽤于配置字段。
在这里插入图片描述
我们修改索引名称的匹配⽅式即可,下⾯2个选项不⽤勾选。点击create,会展⽰出当前配置的索引的域
信息,如下图:
在这里插入图片描述
域的每个标题选项分别代表如下意思:
在这里插入图片描述

7.2.2 数据搜索

Discover为数据搜索部分,可以对⽇志信息进⾏搜索操作
在这里插入图片描述
可以使⽤Discover实现数据搜索过滤和搜索条件显⽰以及关键词搜索,如下图:
在这里插入图片描述

7.2.3 DSL语句使⽤

7.2.3.1 Query DSL结构化查询介绍

Query DSL是⼀个Java开源框架⽤于构建类型安全的SQL查询语句。采⽤API代替传统的拼接字符串来
构造查询语句。⽬前Querydsl⽀持的平台包括JPA,JDO,SQL,Java Collections,RDF,Lucene,
Hibernate Search。elasticsearch提供了⼀整套基于JSON的DSL语⾔来定义查询。

7.2.3.2 索引操作

(1)查询所有索引
GET /_cat/indices?v
结果如下:
在这里插入图片描述
(2)删除某个索引
DELETE /skuinfo
效果如下:
在这里插入图片描述
(3)新增索引
PUT /user
效果如下:
在这里插入图片描述
(4)创建映射

PUT /user/userinfo/_mapping
{
 "properties": {
 "name":{
 "type": "text",
 "analyzer": "ik_smart",
 "search_analyzer": "ik_smart"
 },
 "city":{
 "type": "text",
 "analyzer": "ik_smart",
 "search_analyzer": "ik_smart"
 },
 "age":{
 "type": "long"
 },
 "description":{
 "type": "text",
 "analyzer": "ik_smart",
 "search_analyzer": "ik_smart"
 }
 }
}

(5)新增⽂档数据

PUT /user/userinfo/1
{
 "name":"李四",
 "age":22,
 "city":"深圳",
 "description":"李四来⾃湖北武汉!"
}

(6)修改数据
a.替换操作
更新数据可以使⽤之前的增加操作,这种操作会将整个数据替换掉,代码如下:

#更新数据,id=4
PUT /user/userinfo/4
{
 "name":"张三丰",
 "description":"在武汉读书,家在武汉!在深圳⼯作!"
}

效果如下:
在这里插入图片描述

使⽤GET命令查看:
#根据ID查询
GET /user/userinfo/4
效果如下:
在这里插入图片描述
b.更新操作
我们先使⽤下⾯命令恢复数据

#恢复⽂档数据 id=4
PUT /user/userinfo/4
{
 "name":"张三丰",
 "age":66,
 "city":"武汉",
 "description":"在武汉读书,家在武汉!"
}

使⽤POST更新某个列的数据

#使⽤POST更新某个域的数据
POST /user/userinfo/4/_update
{
 "doc":{
 "name":"张三丰",
 "description":"在武汉读书,家在武汉!在深圳⼯作!"
 }
}

效果如下:
在这里插入图片描述
使⽤GET命令查看:

#根据ID查询
GET /user/userinfo/4

效果如下:
在这里插入图片描述
(7)删除Document

#删除数据
DELETE user/userinfo/7
7.2.3.3 数据查询

(1)查询所有数据

#查询所有
GET /user/_search

效果如下:
在这里插入图片描述
(2)根据ID查询

#根据ID查询
GET /user/userinfo/2

效果如下:
在这里插入图片描述
(3)Sort排序

#搜索排序
GET /user/_search
{
 "query":{
 "match_all": {} 
},
 "sort":{
 "age":{
 "order":"desc"
 }
 }
}

效果如下:
在这里插入图片描述
(4)分页

#分⻚实现
GET /user/_search
{
 "query":{
 "match_all": {}
 },
 "sort":{
 "age":{
 "order":"desc"
 }
 },
 "from": 0,
 "size": 2
}

解释:
from:从下N的记录开始查询
size:每页显⽰条数
效果如下:
在这里插入图片描述

7.2.3.4 查询模式

(1)term查询
term主要⽤于分词精确匹配,如字符串、数值、⽇期等(不适合情况:1.列中除英⽂字符外有其它值 2.
字符串值中有冒号或中⽂ 3.系统⾃带属性如_version)
如下案例:

#查询-term
GET _search
{
 "query":{
 "term":{
 "city":"武汉"
 }
 }
}

效果如下:
在这里插入图片描述
(2)terms 查询
terms 跟 term 有点类似,但 terms 允许指定多个匹配条件。 如果某个字段指定了多个值,那么⽂档需
要⼀起去做匹配 。
案例如下:

#查询-terms 允许多个Term
GET _search
{
 "query":{
 "terms":{
 "city":
 [
 "武汉",
 "⼴州"
 ]
 }
 }
}

效果如下:
在这里插入图片描述
(3)match查询

GET _search
{
 "query": {
 "match": {
 "city": "⼴州武汉"
 }
 }
}

(4)query_string查询

GET _search
{
 "query": {
 "query_string": {
 "default_field": "city",
 "query": "⼴州武汉"
 }
 }
}

(5) range 查询
range过滤允许我们按照指定范围查找⼀批数据。例如我们查询年龄范围
案例如下:

#-range 范围过滤
#gt表示> gte表示=>
#lt表示< lte表示<=
GET _search
{
 "query":{
 "range": {
 "age": {
 "gte": 30,
 "lte": 57
 }
 }
 }
}

上图效果如下:
在这里插入图片描述
(4)exists
exists 过滤可以⽤于查找拥有某个域的数据
案例如下:

#搜索 exists:是指包含某个域的数据检索
GET _search
{
 "query": {
 "exists":{
 "field":"address"
 }
 }
}

效果如下:
在这里插入图片描述
(5) bool 查询
bool 可以⽤来合并多个条件查询结果的布尔逻辑,它包含⼀下操作符:
   must : 多个查询条件的完全匹配,相当于 and。
   must_not : 多个查询条件的相反匹配,相当于 not。
   should : ⾄少有⼀个查询条件匹配, 相当于 or。
这些参数可以分别继承⼀个过滤条件或者⼀个过滤条件的数组:
案例如下:

#过滤搜索 bool
#must : 多个查询条件的完全匹配,相当于 and。
#must_not : 多个查询条件的相反匹配,相当于 not。
#should : ⾄少有⼀个查询条件匹配, 相当于 or。
GET _search
{
 "query": {
 "bool": {
 "must": [
 {
 "term": {
 "city": {
"value": "深圳"
 }
 }
 },
 {
 "range":{
 "age":{
 "gte":20,
 "lte":99
 }
 }
 }
 ]
 }
 }
}

效果如下:
在这里插入图片描述
(6) match_all 查询
可以查询到所有⽂档,是没有查询条件下的默认语句。
案例如下:

#查询所有 match_all
GET _search
{
 "query": {
 "match_all": {}
 }
}

(7) match 查询
match查询是⼀个标准查询,不管你需要全⽂本查询还是精确查询基本上都要⽤到它。
如果你使⽤ match 查询⼀个全⽂本字段,它会在真正查询之前⽤分析器先分析match⼀下查询字符:
案例如下:

#字符串匹配
GET _search
{
 "query": {
 "match": {
 "description": "武汉"
 }
 }
}

效果如下:
在这里插入图片描述
(8)prefix 查询
以什么字符开头的,可以更简单地⽤ prefix ,例如查询所有以张开始的⽤户描述
案例如下:

#前缀匹配 prefix
GET _search
{
 "query": {
 "prefix": {
 "name": {
 "value": "赵"
 }
 }
 }
}

效果如下:
在这里插入图片描述
(9)multi_match 查询
multi_match查询允许你做match查询的基础上同时搜索多个字段,在多个字段中同时查⼀个
案例如下:

#多个域匹配搜索
GET _search
{
 "query": {
 "multi_match": {
 "query": "深圳",
 "fields": [
 "city",
 "description"
 ]
 }
 }
}

效果如下:
在这里插入图片描述

7.2.3.5 完整DSL语句代码
#查看所有索引
GET /_cat/indices?v
#删除某个索引
DELETE /skuinfo
#新增索引
PUT /user
#创建映射
PUT /user/userinfo/_mapping
{
 "properties": {
 "name":{
 "type": "text",
 "analyzer": "ik_smart",
 "search_analyzer": "ik_smart",
 "store": false
 },
 "city":{
 "type": "text",
 "analyzer": "ik_smart",
 "search_analyzer": "ik_smart",
 "store": false
 },
 "age":{
 "type": "long",
 "store": false
 },
 "description":{
 "type": "text",
 "analyzer": "ik_smart",
 "search_analyzer": "ik_smart",
 "store": false
 }
 }
}
#新增⽂档数据 id=1
PUT /user/userinfo/1
{
 "name":"李四",
 "age":22,
 "city":"深圳",
 "description":"李四来⾃湖北武汉!"
}
#新增⽂档数据 id=2
PUT /user/userinfo/2
{
 "name":"王五",
 "age":35,
 "city":"深圳",
 "description":"王五家住在深圳!"
}
#新增⽂档数据 id=3
PUT /user/userinfo/3
{
 "name":"张三",
"age":19,
 "city":"深圳",
 "description":"在深圳打⼯,来⾃湖北武汉"
}
#新增⽂档数据 id=4
PUT /user/userinfo/4
{
 "name":"张三丰",
 "age":66,
 "city":"武汉",
 "description":"在武汉读书,家在武汉!"
}
#新增⽂档数据 id=5
PUT /user/userinfo/5
{
 "name":"赵⼦⻰",
 "age":77,
 "city":"⼴州",
 "description":"赵⼦⻰来⾃深圳宝安,但是在⼴州⼯作!",
 "address":"⼴东省茂名市"
}
#新增⽂档数据 id=6
PUT /user/userinfo/6
{
 "name":"赵毅",
 "age":55,
 "city":"⼴州",
 "description":"赵毅来⾃⼴州⽩云区,从事电⼦商务8年!"
}
#新增⽂档数据 id=7
PUT /user/userinfo/7
{
 "name":"赵哈哈",
 "age":57,
 "city":"武汉",
 "description":"武汉赵哈哈,在深圳打⼯已有半年了,⽉薪7500!"
}
#更新数据,id=4
PUT /user/userinfo/4
{
 "name":"张三丰",
 "description":"在武汉读书,家在武汉!在深圳⼯作!"
}
#根据ID查询
GET /user/userinfo/4
#恢复⽂档数据 id=4
PUT /user/userinfo/4
{
 "name":"张三丰",
 "age":66,
 "city":"武汉",
 "description":"在武汉读书,家在武汉!"
}
#使⽤POST更新某个域的数据
POST /user/userinfo/4/_update
{
 "doc":{
 "name":"张三丰",
 "description":"在武汉读书,家在武汉!在深圳⼯作!"
 }
}
#根据ID查询
GET /user/userinfo/4
#删除数据
DELETE user/userinfo/4
#查询所有
GET /user/_search
#根据ID查询
GET /user/userinfo/2
#搜索排序
GET /user/_search
{
 "query":{
 "match_all": {}
 },
 "sort":{
 "age":{
 "order":"desc"
 }
 }
}
#分⻚实现
GET /user/_search
{
 "query":{
 "match_all": {}
 },
 "sort":{
 "age":{
"order":"desc"
 }
 },
 "from": 0,
 "size": 2
}
#查询-term
GET _search
{
 "query":{
 "term":{
 "city":"武汉"
 }
 }
}
#查询-terms 允许多个Term
GET _search
{
 "query":{
 "terms":{
 "city":
 [
 "武汉",
 "⼴州"
 ]
 }
 }
}
#match查询
GET _search
{
 "query": {
 "match": {
 "description": "武汉"
 }
 }
}
#过滤-range 范围过滤
#gt表示> gte表示=>
#lt表示< lte表示<=
GET _search
{
 "query":{
 "range": {
 "age": {
 "gte": 30,
 "lte": 57
 }
}
 }
}
#过滤搜索 exists:是指包含某个域的数据检索
GET _search
{
 "query": {
 "exists":{
 "field":"address"
 }
 }
}
#过滤搜索 bool
#must : 多个查询条件的完全匹配,相当于 and。
#must_not : 多个查询条件的相反匹配,相当于 not。
#should : ⾄少有⼀个查询条件匹配, 相当于 or。
GET _search
{
 "query": {
 "bool": {
 "must": [
 {
 "term": {
 "city": {
 "value": "深圳"
 }
 }
 },
 {
 "range":{
 "age":{
 "gte":20,
 "lte":99
 }
 }
 }
 ]
 }
 }
}
#查询所有 match_all
GET _search
{
 "query": {
 "match_all": {}
 }
}
#字符串匹配
GET _search
{
 "query": {
 "match": {
 "description": "武汉"
 }
 }
}
#前缀匹配 prefix
GET _search
{
 "query": {
 "prefix": {
 "name": {
 "value": "赵"
 }
 }
 }
}
#多个域匹配搜索
GET _search
{
 "query": {
 "multi_match": {
 "query": "深圳",
 "fields": [
 "city",
 "description"
 ]
 }
 }
}
#过滤-range 范围过滤
#gt表示> gte表示=>
#lt表示< lte表示<=
GET _search
{
 "query": {
 "bool": {
 "must": [
 {"match": {
 "city": "深圳武汉"
 }}
 ],
 "filter": {
 "range": {
 "age": {
 "gte": 20,
"lte": 60
 }
 }
 }
 }
 }
}

因为过滤可以使⽤缓存,同时不计算分数,通常的规则是,使⽤查询(query)语句来进⾏ 全⽂ 搜索或
者其它任何需要影响 相关性得分 的搜索。除此以外的情况都使⽤过滤(filters)。

⼋、ElasticSearch编程操作

8.1 创建⼯程,导⼊坐标

pom.xml坐标

<dependencies>
 <dependency>
 <groupId>org.elasticsearch</groupId>
 <artifactId>elasticsearch</artifactId>
 <version>5.6.8</version>
 </dependency>
 <dependency>
 <groupId>org.elasticsearch.client</groupId>
 <artifactId>transport</artifactId>
 <version>5.6.8</version>
 </dependency>
 <dependency>
 <groupId>org.apache.logging.log4j</groupId>
 <artifactId>log4j-to-slf4j</artifactId>
 <version>2.9.1</version>
 </dependency>
 <dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-api</artifactId>
 <version>1.7.24</version>
 </dependency>
 <dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-simple</artifactId>
 <version>1.7.21</version>
 </dependency>
 <dependency>
 <groupId>log4j</groupId>
 <artifactId>log4j</artifactId>
<version>1.2.12</version>
 </dependency>
 <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <version>4.12</version>
 </dependency>
</dependencies>

8.2创建索引index

@Test
//创建索引
public void test1() throws Exception{
//1.设置加入的集群
Settings settings = Settings.builder().put("cluster.name", "myelasticsearch").build();
//2.创建Client连接对象
TransportClient client = new PreBuiltTransportClient(settings)
 .addTransportAddress(new
InetSocketTransportAddress(InetAddress.getByName("192.168.220.100"), 9300));
//3.创建名称为blog2的索引
client.admin().indices().prepareCreate("blog2").get();
//4.释放资源
client.close();
}

在这里插入图片描述
在这里插入图片描述

8.3创建映射mapping

@Test
//创建映射
public void test3() throws Exception{
 // 创建Client连接对象
 Settings settings = Settings.builder().put("cluster.name", "myelasticsearch").build();
 TransportClient client = new PreBuiltTransportClient(settings)
 .addTransportAddress(new
InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9300));
 
 // 添加映射
 /**
 * 格式:
 * "mappings" : {
 "article" : {
 "dynamic" : "false",
 "properties" : {
 "id" : { "type" : "string" },
 "content" : { "type" : "string" },
 "author" : { "type" : "string" }
 }
 }
 }
 */
XContentBuilder builder = XContentFactory.jsonBuilder()
 .startObject()
 .startObject("article")
 .startObject("properties")
 .startObject("id")
 .field("type", "integer").field("store", "yes")
 .endObject()
 .startObject("title")
 .field("type", "string").field("store", "yes").field("analyzer",
"ik_smart")
 .endObject()
 .startObject("content")
 .field("type", "string").field("store", "yes").field("analyzer",
"ik_smart")
 .endObject()
 .endObject()
 .endObject()
 .endObject();
 // 创建映射
 PutMappingRequest mapping = Requests.putMappingRequest("blog2")
 .type("article").source(builder);
 client.admin().indices().putMapping(mapping).get();
 //释放资源
 client.close();
}

在这里插入图片描述
在这里插入图片描述

8.4建⽴⽂档document

8.4.1 建⽴⽂档(通过XContentBuilder)

@Test
 public void testAddDocument() throws Exception {
 //创建⼀个client对象
 //创建⼀个⽂档对象
 XContentBuilder builder = XContentFactory.jsonBuilder()
 .startObject()
 .field("id",2l)
 .field("title","北⽅⼊秋速度明显加快 多地降温幅度最多可达1022222")
 .field("content", "阿联酋⼀架客机在纽约机场被隔离 10名乘客病倒"
 .endObject();
 //把⽂档对象添加到索引库
 client.prepareIndex()
 //设置索引名称
 .setIndex("index_hello")
 //设置type
 .setType("article")
 //设置⽂档的id,如果不设置的话⾃动的⽣成⼀个id
 .setId("2")
 //设置⽂档信息
 .setSource(builder)
 //执⾏操作
 .get();
 //关闭客户端
 client.close();
 }

在这里插入图片描述

8.4.2 建⽴⽂档(使⽤Jackson转换实体)

(1)创建Article实体

public class Article {
 private Integer id;
 private String title;
 private String content;
 getter/setter...
}

(2)添加jackson坐标

<dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-core</artifactId>
 <version>2.8.1</version>
</dependency>
<dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-databind</artifactId>
 <version>2.8.1</version>
</dependency>
<dependency>
 <groupId>com.fasterxml.jackson.core</groupId>
 <artifactId>jackson-annotations</artifactId>
 <version>2.8.1</version>
</dependency>

( 3)代码实现

@Test
 public void testAddDocument2() throws Exception {
 //创建⼀个Article对象
 Article article = new Article();
 //设置对象的属性
 article.setId(3l);
 article.setTitle("MH370坠毁在柬埔寨密林?中国⼀公司调⼗颗卫星去拍摄");
 article.setContent("警惕荒唐的死亡游戏!俄15岁少年输掉游戏后⽤电锯⾃杀");
 //把article对象转换成json格式的字符串。
 ObjectMapper objectMapper = new ObjectMapper();
 String jsonDocument = objectMapper.writeValueAsString(article);
 System.out.println(jsonDocument);
 //使⽤client对象把⽂档写⼊索引库
 client.prepareIndex("index_hello","article", "3")
 .setSource(jsonDocument, XContentType.JSON)
 .get();
 //关闭客户端
 client.close();
 }

在这里插入图片描述

@Test
public void testAddDocument3() throws Exception {
 for (int i = 4; i < 100; i++) {
 //创建⼀个Article对象
 Article article = new Article();
 //设置对象的属性
 article.setId(i);
 article.setTitle("⼥护⼠路遇昏迷男⼦跪地抢救:救⼈是职责更是本能" + i);
 article.setContent("江⻄变质营养餐事件已致24⼈就医 多名官员被调查" + i);
 //把article对象转换成json格式的字符串。
 ObjectMapper objectMapper = new ObjectMapper();
 String jsonDocument = objectMapper.writeValueAsString(article);
 System.out.println(jsonDocument);
 //使⽤client对象把⽂档写⼊索引库
 client.prepareIndex("index_hello","article", i + "")
 .setSource(jsonDocument, XContentType.JSON)
 .get();
 }
 //关闭客户端
 client.close();
}

8.5 查询⽂档操作

8.5.1 termQuery

@Test
 public void testQueryByTerm() throws Exception {
 //创建⼀个QueryBuilder对象
 //参数1:要搜索的字段
 //参数2:要搜索的关键词
 QueryBuilder queryBuilder = QueryBuilders.termQuery("title", "美丽的⼥
护⼠");
 //执⾏查询
 SearchResponse searchResponse = client.prepareSearch("index_hello")
 .setTypes("article")
 .setQuery(queryBuilder)
 .get();
 //取查询结果
 SearchHits searchHits = searchResponse.getHits();
 //取查询结果的总记录数
 System.out.println("查询结果总记录数:" + searchHits.getTotalHits());
//查询结果列表
 Iterator<SearchHit> iterator = searchHits.iterator();
 while(iterator.hasNext()) {
 SearchHit searchHit = iterator.next();
 //打印⽂档对象,以json格式输出
 System.out.println(searchHit.getSourceAsString());
 //取⽂档的属性
 System.out.println("-----------⽂档的属性");
 Map<String, Object> document = searchHit.getSource();
 System.out.println(document.get("id"));
 System.out.println(document.get("title"));
 System.out.println(document.get("content"));
 }
 //关闭client
 client.close();
 } 

8.5.2 QueryString

@Test
 public void testQueryByQueryString() throws Exception {
 //创建⼀个QueryBuilder对象
 //参数1:要搜索的字段
 //参数2:要搜索的关键词
 QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("美丽的⼥护
⼠").defaultField("title");
 //执⾏查询
 SearchResponse searchResponse = client.prepareSearch("index_hello")
 .setTypes("article")
 .setQuery(queryBuilder)
 .get();
 //取查询结果
 SearchHits searchHits = searchResponse.getHits();
 //取查询结果的总记录数
 System.out.println("查询结果总记录数:" + searchHits.getTotalHits());
 //查询结果列表
 Iterator<SearchHit> iterator = searchHits.iterator();
 while(iterator.hasNext()) {
 SearchHit searchHit = iterator.next();
 //打印⽂档对象,以json格式输出
 System.out.println(searchHit.getSourceAsString());
 //取⽂档的属性
 System.out.println("-----------⽂档的属性");
 Map<String, Object> document = searchHit.getSource();
System.out.println(document.get("id"));
 System.out.println(document.get("title"));
 System.out.println(document.get("content"));
 }
 //关闭client
 client.close();
 } 

8.5.3 MatchQuery

@Test
public void testQueryByMatchQuery() throws Exception {
 //创建⼀个QueryBuilder对象
 //参数1:要搜索的字段
 //参数2:要搜索的关键词
 QueryBuilder queryBuilder = QueryBuilders.matchQuery("title", "美丽的⼥护
⼠");
 //执⾏查询
 SearchResponse searchResponse = client.prepareSearch("index_hello")
 .setTypes("article")
 .setQuery(queryBuilder)
 .get();
 //取查询结果
 SearchHits searchHits = searchResponse.getHits();
 //取查询结果的总记录数
 System.out.println("查询结果总记录数:" + searchHits.getTotalHits());
 //查询结果列表
 Iterator<SearchHit> iterator = searchHits.iterator();
 while(iterator.hasNext()) {
 SearchHit searchHit = iterator.next();
 //打印⽂档对象,以json格式输出
 System.out.println(searchHit.getSourceAsString());
 //取⽂档的属性
 System.out.println("-----------⽂档的属性");
 Map<String, Object> document = searchHit.getSource();
 System.out.println(document.get("id"));
 System.out.println(document.get("title"));
 System.out.println(document.get("content"));
 }
 //关闭client
 client.close();
} 

8.5.4 查询后分页⽅法

private void search(QueryBuilder queryBuilder) throws Exception {
 //执⾏查询
 SearchResponse searchResponse = client.prepareSearch("index_hello")
 .setTypes("article")
 .setQuery(queryBuilder)
 //设置分⻚信息
 .setFrom(0)
 //每⻚显示的⾏数
 .setSize(5)
 .get();
 //取查询结果
 SearchHits searchHits = searchResponse.getHits();
 //取查询结果的总记录数
 System.out.println("查询结果总记录数:" + searchHits.getTotalHits());
 //查询结果列表
 Iterator<SearchHit> iterator = searchHits.iterator();
 while(iterator.hasNext()) {
 SearchHit searchHit = iterator.next();
 //打印⽂档对象,以json格式输出
 System.out.println(searchHit.getSourceAsString());
 //取⽂档的属性
 System.out.println("-----------⽂档的属性");
 Map<String, Object> document = searchHit.getSource();
 System.out.println(document.get("id"));
 System.out.println(document.get("title"));
 System.out.println(document.get("content"));
 }
 //关闭client
 client.close();
}

8.5.5 使⽤⽂档ID查询⽂档

@Test
 public void testSearchById() throws Exception {
 //创建⼀个client对象
 //创建⼀个查询对象
 QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds("1",
"2");
 search(queryBuilder);
 }

8.5.6查询⽂档分页操作

@Test // 查询⽂档分页操作
public void testQueryMatchAllQuery() throws Exception {
    //创建⼀个QueryBuilder对象
    QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
    //执⾏查询
    search(queryBuilder);
}

8.6 查询结果⾼亮操作

8.6.1 什么是⾼亮显⽰

在进⾏关键字搜索时,搜索出的内容中的关键字会显⽰不同的颜⾊,称之为⾼亮百度搜索关键字"开课吧"
在这里插入图片描述

8.6.2 ⾼亮显⽰的html分析

在这里插入图片描述

8.6.3 ⾼亮显⽰代码实现

@Test
 public void highlightSearchTest() throws Exception {
 QueryBuilder queryBuilder = QueryBuilders.multiMatchQuery("北京市⺠",
"title", "content");
 HighlightBuilder highlightBuilder = new HighlightBuilder();
 highlightBuilder.field("title").field("content");
 highlightBuilder.preTags("<em>");
 highlightBuilder.postTags("</em>");
 //执⾏查询
 SearchResponse searchResponse = client.prepareSearch("index_hello")
 .setTypes("article")
 .setQuery(queryBuilder)
 //设置⾼亮信息
 .highlighter(highlightBuilder)
.get();
 //取查询结果
 SearchHits searchHits = searchResponse.getHits();
 //取查询结果的总记录数
 System.out.println("查询结果总记录数:" + searchHits.getTotalHits());
 //查询结果列表
 Iterator<SearchHit> iterator = searchHits.iterator();
 while(iterator.hasNext()) {
 SearchHit searchHit = iterator.next();
 //取⽂档的属性
 System.out.println("-----------⽂档的属性");
 Map<String, Object> document = searchHit.getSource();
 System.out.println(document.get("id"));
 System.out.println(document.get("title"));
 System.out.println(document.get("content"));
 System.out.println("************⾼亮结果");
 Map<String, HighlightField> highlightFields =
searchHit.getHighlightFields();
// //取title⾼亮显示的结果
 if (highlightFields.size() <=0) continue;
 for (Map.Entry<String, HighlightField> entry :
highlightFields.entrySet()) {
 System.out.println(entry.getKey() + ":\t" +
Arrays.toString(entry.getValue().getFragments()));
 }
 }
 //关闭client
 client.close();
 }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值