ElasticSearch
Elaticsearch简称es,es是一个开源的高扩展的分布式全文搜索引擎,它可以近乎实现实时存储,检索数据,本身扩展性好,可以扩展到上百台服务器,处理PB级别的数据.es也是用java开发,并使用Lucene作为核心来实现所有和搜索的功能,但是它的目的是通过简单的RestFul API来隐藏Lucene的复杂性,让全文搜索变得简单
2016年,ElasticSearch已经超过solr等,成为排名第一的搜索引擎应用
它用于全文搜索,结构化搜索,分析以及将这三者混合使用
危机便可使用ElasticSearch提供全问搜索并且高亮关键字,以及输入实时搜索(search-asyou-type)和搜索纠错,(did-you-mean)等搜索建议功能.
Elasticearch是一个基于Apache Lucene(TM)的开源搜索引擎.无论是在开源还是专有领域,Luncene开源被认为是迄今为止最先进的,性能最好的全问搜索引擎.
但是,Luncene只是一个库.想要使用它,你必须使用java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Luncene非常复杂,需要深入了解检索的相关知识来理解它是如何工作的.
使用场景
案例
- 维基百科
- The Guardian
- Stack overFlow
- Github
- 电商网站
- 日志数据分析 logstash采集日志,es进行数据分析 ELK技术,elasticsearch+logstash+kibana
- 商品价格监控网站
- BI系统
solr
solr是apche下的一个顶级开源项目,采用java开发,是基于Luncene的全文搜索服务器,Solr提供了比Luncene更为丰富的查询语言,同时实现了可配置,可扩展,并对所有,搜索性能进行了优化.
solr开源独立运行在Jetty,Tomcat等这些servlet容器中,solr所有的实现方法很简单,用post方法向solr服务器发送一个描述Field及其内容的XMlL文档,solr根据XML文档添加删除,更新索引.Solr搜索只需发送HTtp get请求,然后对Solr返回XML Json结果进行解析,组织页面布局,Solr不提供构建UI的功能,Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况
lucene
lucene是apache软件基金会4 jakarta项目中的一个子项目,是一个开放源代码的全问搜索引擎工具包,但它不是一个完整的全问搜索引擎,而是一个全问搜索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文俩种西方语言).lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便在目标系统中实现全文检索功能,或者说以此为基础建立起完整的全文搜索引擎.在java开发环境里lucene是一个成熟的免费开源工具.就其本身而言,lucene是当前以及最简几年最受欢迎的java信息检索程序库.
lucene是一个全文搜索引擎架构,那么什么是全文搜索引擎?
全文搜索引擎是名副其实的搜索引擎,比如Google,Fast,国内的百度.它们都是通过从互联网上提取各个网站的信息,检索与用户查询条件匹配的相关记录,然后按一定的排列顺序返回给用户,因而它们是真正的搜索引擎
比较
Elasticsearch和solr优缺点比较
- 当单纯的对已有数据进行搜索时,solr更快
- 当监理索引时,solr会产生io阻塞,elasticsearch具有明显优势
- 随着数据量的增加,Solr的搜索效率会变得很低,es几乎没有变化
差异
- es是开箱即用,Solr安装略微复杂一点
- Solr利用zookeeper进行分部署管理,而Elasticsearch自身带有分布式协调管理功能
- Solr支持更多格式的数据,比如,json,xml,csv,而es仅支持json文件格式
- solr官方提供的功能更多,而es本身更加注重于核心功能,高级功能是第三方插件提供,例如图形需要kibana支撑
- solr查询快,但更新慢
- solr比较成熟,更大,es维护更新快
搭建
目录
- bin 启动文件
config 配置文件
- log4j2 日志配置文件
- jvm.options 虚拟机相关配置
- elasticsearch.yml es的配置文件默认9200端口
- lib 相关jar包
- log 日志
- modules 功能模块
- plgins 插件
访问
访问默认的9200端口返回
{
"name" : "DESKTOP-2PBFFCG",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "l3jmEEiRTIKuegUjuR9ONQ",
"version" : {
"number" : "7.6.1",
"build_flavor" : "default",
"build_type" : "zip",
"build_hash" : "aa751e09be0a5072e8570670309b1f12348f023b",
"build_date" : "2020-02-29T00:15:25.529771Z",
"build_snapshot" : false,
"lucene_version" : "8.4.0",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
可视化
插件下载
GitHub - mobz/elasticsearch-head: A web front end for an elastic search cluster
直接npm install 然后npm run start
es文件修改
加上
http.cors.enabled: true
http.cors.allow-origin: "*"
开启跨域
然后访问http://localhost:9100/
索引就类似一个数据库,文档就好比库中的数据
head就当做数据展示工具,后面做的查询都可以去kibana中做
ELK
ELK是Elasticsearch,Logstash,Kibana三大开源框架的简称
Logstash是ELK的中央数据流引擎,用于从不同目标(文件/数据存储/MQ)收集不同格式数据,经过过滤后支持输出到不同的目的地(问/MQ/redis/elasticsearch/kafka等).
Kibana可以将es的数据通过友好的界面展示出来,提供实时的分析功能
Kibana安装
下载解压后的目录
默认Kibana端口5601
开发工具
Kibana汉化
修改kibana.yml
最后一行加上
i18n.locale: "zh-CN"
核心概念
elatiseach是面向文档,和关系型数据库比,一切都是json
RelationalDB | Elasticsearch |
---|---|
数据库(database) | 索引(indices) |
表(table) | types (慢慢会被弃用) |
行(row) | documents 文档 |
字段(columns) | fields |
elasticearch中可以包含多个索引,每个索引中可以包含多个类型,类型中又包含多个文档,每个文档中又包含多个字段
物理设计
elasticsearch在后台把每个索引划分成多个切片,每个分片可以在集群中的不同服务器间迁移
一个es就是一个集群,默认的集群名称就是elasticsearch
逻辑设计
文档
es是面向文档的,这就意味着索引和搜索的最小单位是文档 es中有几个主要的属性,
- 自我包含,一篇文档同时包含字段和对应的值,也就是同时包含key:value
- 可以是层次的,一个文档中包含自文档,复杂的逻辑就是这么来的
- 灵魂的结构,文档不依赖预先定义的模式,我们知道关系型数据库中,要提前定义字段才能使用,es中对于字段是非常灵活的,有时候可以忽略字段,或者动态添加一个字段
监管我们可以随意的新增或者忽略某个字段,但是每个字段的类型非常重要,比如一个年龄类型字段,可以是字符串也可以是整形,因为es会保存字段和类型之间映射以及其他的设置,这种映射具体到每个映射的每种类型,这也是为什么在es中,类型有点时候也称为映射类型
类型
类型是文档的逻辑日期,就像关系型数据库一样,表格是行的容器,类型中对于字段的定义称为映射,比如name映射为字符串类型.我们说文档是无模式的,它们不需要拥有映射所定义的所有字段,比如新增一个字段,那么es是怎么做的呢?es会自动的将新字段假如映射,但是这个字段不确定它是什么类型,es就开始猜,如果这个值是18,那么es就会认为它是整形.但es可能猜不对,所以最安全的方式就是提前定义好所需的映射,这点跟关系型数据库殊途同归.
索引
所以是映射类型的容器,es中的索引是非常大的文档集合,所以存储了映射类型的字段和其他设置.然后他们被存储到各个分片上了.
工作方式
一个集群至少有一个节点,一个节点就是一个es进程,节点可以有多个索引默认的,如果你创建索引,那么索引将会有五个分片构成,又称之为主分片(primary shard)构成的,每一个主分片会有一个副本(replica shard又称为复制分片)
上图是有三个节点的集群,我可以看到主分片和对应的复制分片都不会在同一个节点内,这样有利于某个节点挂掉了,数据也不至于丢失,实际上一个分片是一个lucene索引,一个包含倒排序的文件目录,倒排序索引的结构使得es在不扫描全部文档的情况下,就能告诉你哪些文档包含特定的关键字
倒排序索引
es使用的是一种称为倒排索引的结构,采用lucene倒序作为底层,这种和结构适用于快速的全文搜索,一个索引由文档中所有不重复的列表构成,对于每一个单词,都有一个包含它的文档列表.
为了创建倒排索引,我们首先药将每个文档拆封成独立的词,然后创建一个包含所有不重复的词条的排序列表,然后列出每个词条现在哪个文档
如果俩个文档都匹配,但是第一个文档比第二个文档匹配程度更高,如果没有别的条件,现在,这俩个包含关键字的文档都将被返回
相对于查找所有原始数据而言,查找倒排索引后的数据会快的多.只需要查看标签这一栏,然后获取文章的id即可,完全过滤掉无关的数据
es中索引被分成多个片,每个分片都是lucene所以.所以一个二十索引是多个lucene索引组成的
插件
IK分词器
分词就是把一段中文或者别的划分成一个个的关键字,我们在搜索时候会把自己的信息进行分词查,会把数据库中或者索引库中的数据进行分词,然后进行一个匹配操作,默认的中文分词是每一个字看成一个词,
如果使用中文建议使用ik分词器
下载对应的版本然后拖进插件目录就可以
重启es可以看到ik分词器被加载
输入elasticsearch-plugin list
就可以看到插件
使用
什么是ik分词器
IK提供了俩个分词算法,ik_sart和ik_max_word,其中ik_smart为最少切分,ik_max_word为最细粒度划分
在Kibana 中发起请求
GET _analyze
{
"analyzer": "ik_smart",
"text": "中国共产党"
}
结果
{
"tokens" : [
{
"token" : "中国共产党",
"start_offset" : 0,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 0
}
]
}
如果发送
GET _analyze
{
"analyzer": "ik_max_word",
"text": "中国共产党"
}
则返回
{
"tokens" : [
{
"token" : "中国共产党",
"start_offset" : 0,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 0
},
{
"token" : "中国",
"start_offset" : 0,
"end_offset" : 2,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "国共",
"start_offset" : 1,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 2
},
{
"token" : "共产党",
"start_offset" : 2,
"end_offset" : 5,
"type" : "CN_WORD",
"position" : 3
},
{
"token" : "共产",
"start_offset" : 2,
"end_offset" : 4,
"type" : "CN_WORD",
"position" : 4
},
{
"token" : "党",
"start_offset" : 4,
"end_offset" : 5,
"type" : "CN_CHAR",
"position" : 5
}
]
}
如果自己需要加词语到分词器字典中
ik的config目录下有一个文件
IKAnalyzer.cfg.xml
<?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"></entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
修改
<?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">my.dic</entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<!-- <entry key="remote_ext_dict">words_location</entry> -->
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
在当前目录下创建my.dic
如果设置了
GET _analyze
{
"analyzer": "ik_max_word",
"text": "那随忆了"
}
就会变成
{
"tokens" : [
{
"token" : "那",
"start_offset" : 0,
"end_offset" : 1,
"type" : "CN_CHAR",
"position" : 0
},
{
"token" : "随忆",
"start_offset" : 1,
"end_offset" : 3,
"type" : "CN_WORD",
"position" : 1
},
{
"token" : "了",
"start_offset" : 3,
"end_offset" : 4,
"type" : "CN_CHAR",
"position" : 2
}
]
}
(原来是四个字都是分开的
索引基本操作
put新增
创建一个索引
PUT /索引名/类型名/文档id {请求体}
插入
PUT /test1/type1/1
{
"name": "随亿",
"age":18
}
结果
#! Deprecation: [types removal] Specifying types in document index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, or /{index}/_create/{id}).
{
"_index" : "test1", //索引
"_type" : "type1", //类型
"_id" : "1", //id
"_version" : 1,
"result" : "created", //创建状态
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
在head选中索引就可以进行查看
类型
那么数据库中有哪些常用类型呢
- 字符串类型 text,key
- 数值类型 long,integer,short,byte,double,float,half float,scaled float
- 日期类型 date
- 布尔值类型 boolean
- 二进制类型 binary
- 等等
自己设置类型
PUT /test2
{
"mappings": {
"properties": {
"name":{
"type":"text"
},
"age":{
"type":"long"
},
"birthday":{
"type":"date"
}
}
}
}
类似于建立数据表
返回
{
"acknowledged" : true,
"shards_acknowledged" : true,
"index" : "test2"
}
创建成功
然后用GET test2
查看表结构获取具体信息
{
"test2" : {
"aliases" : { },
"mappings" : {
"properties" : {
"age" : {
"type" : "long"
},
"birthday" : {
"type" : "date"
},
"name" : {
"type" : "text"
}
}
},
"settings" : {
"index" : {
"creation_date" : "1652755677562",
"number_of_shards" : "1",
"number_of_replicas" : "1",
"uuid" : "YqkoIej5RxusmWOWZhqfxw",
"version" : {
"created" : "7060199"
},
"provided_name" : "test2"
}
}
}
}
之后默认就是doc类型的了
PUT /test3/_doc/1
{
"name":"那随意了",
"age":13,
"birth":"1997-01-05"
}
结果
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "1",
"_version" : 1,
"result" : "created",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 0,
"_primary_term" : 1
}
这时候查看当前创建的类型会发现
{
"test3" : {
"aliases" : { },
"mappings" : {
"properties" : {
"age" : {
"type" : "long"
},
"birth" : {
"type" : "date"
},
"name" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
},
"settings" : {
"index" : {
"creation_date" : "1652755917555",
"number_of_shards" : "1",
"number_of_replicas" : "1",
"uuid" : "p8yTyYYlSkm6X06KJ2x58Q",
"version" : {
"created" : "7060199"
},
"provided_name" : "test3"
}
}
}
}
如果文档没指定,文档会自动生成类型
其他命令
GET _cat/health
获取健康值
GET _cat/indices?v
查看数据库的具体信息
修改索引
修改还是使用put,覆盖最新值即可
比如
PUT /test3/_doc/1
{
"name":"那随忆了",
"age":13,
"birth":"1997-01-05"
}
值就被成功修改了
结果
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "1",
"_version" : 2, //版本号增加了
"result" : "updated", //状态为updated
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 1,
"_primary_term" : 1
}
以上是曾经的方法,有一个弊端,万一漏了一条数据那么那个数据就丢失了比如age
post修改
POST /test3/_doc/1/_update
{
"doc":{
"name":"张三"
}
}
结果
#! Deprecation: [types removal] Specifying types in document update requests is deprecated, use the endpoint /{index}/_update/{id} instead.
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "1",
"_version" : 3, //变为第三个版本了
"result" : "updated",
"_shards" : {
"total" : 2,
"successful" : 1,
"failed" : 0
},
"_seq_no" : 2,
"_primary_term" : 1
}
如果最后不加/_update那么就和put没有区别了
删除索引
DELETE test1
根据请求来判断是删除索引还是删除文档记录
删单条数据DELETE test1/type1/1
查询
单条记录
GET test3/_doc/1
全表
GET test3
GET test3/_doc/_search
搜索全表
GET test3/_doc/_search?q=name:张
或者GET test3/_doc/_search?q=name:张三
(精确匹配
结果
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 29,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.5753642,
"hits" : [
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.5753642,
"_source" : {
"name" : "张三",
"age" : 13,
"birth" : "1997-01-05"
}
}
]
}
}
注意! 分词器对keyword字段不会工作
复杂查询
"_score" : 0.5753642,
这个字段代表着分数,如果多条记录中,匹配度越高分值则越高
GET test3/_doc/_search
{
"query":{
"match": {
"name": "张三"
}
}
}
返回结果
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1, //数量
"relation" : "eq" //关系
},
"max_score" : 0.5753642,//最大分值
"hits" : [
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.5753642,
"_source" : {
"name" : "张三",
"age" : 13,
"birth" : "1997-01-05"
}
}
]
}
}
hit中能获取索引和文档的信息,查询的结果总数,然后就是查询出来的具体的文档,数据中的东西都可以遍历出来了,我们可以通过分数来判断谁更加符合结果
可以通过_source来指定要查询出来的字段
GET test3/_doc/_search
{
"query":{
"match": {
"name": "张三"
}
},
"_source":["name","age"]
}
结果
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 2.0834165,
"hits" : [
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "1",
"_score" : 2.0834165,
"_source" : {
"name" : "张三",
"age" : 13
}
}
]
}
}
排序和分页
假如有以下数据
传入
GET test3/_doc/_search
{
"sort":[
{
"age":{
"order":"asc" //排序方式
}
}
],
"from":0, //第几条开始
"size":3 //数量
}
结果
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : null,
"hits" : [
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "1",
"_score" : null,
"_source" : {
"name" : "张三",
"age" : 13,
"birth" : "1997-01-05"
},
"sort" : [
13
]
},
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "2",
"_score" : null,
"_source" : {
"name" : "qwq",
"age" : 18,
"birth" : "2000-01-05"
},
"sort" : [
18
]
},
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "3",
"_score" : null,
"_source" : {
"name" : "阿巴阿巴",
"age" : 20,
"birth" : "2000-08-05"
},
"sort" : [
20
]
}
]
}
}
多个条件
must(类似and)所有条件都要符合
GET test3/_doc/_search
{
"query":{
"bool":{
"must":[
{
"match":{
"name":"张三"
}
},
{
"match":{
"age":13
}
}
]
}
}
}
返回
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 17,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 3.0834165,
"hits" : [
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "1",
"_score" : 3.0834165,
"_source" : {
"name" : "张三",
"age" : 13,
"birth" : "1997-01-05"
}
}
]
}
}
should (类似or)
GET test3/_doc/_search
{
"query":{
"bool":{
"should":[
{
"match":{
"name":"张三"
}
},
{
"match":{
"age":131
}
}
]
}
}
}
结果
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 2.0834165,
"hits" : [
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "1",
"_score" : 2.0834165,
"_source" : {
"name" : "张三",
"age" : 13,
"birth" : "1997-01-05"
}
}
]
}
}
must_not (类似于not)
请求
GET test3/_doc/_search
{
"query":{
"bool":{
"must_not":[
{
"match":{
"name":"张三"
}
},
{
"match":{
"age":131
}
}
]
}
}
}
结果
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 0.0,
"hits" : [
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.0,
"_source" : {
"name" : "qwq",
"age" : 18,
"birth" : "2000-01-05"
}
},
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.0,
"_source" : {
"name" : "阿巴阿巴",
"age" : 20,
"birth" : "2000-08-05"
}
}
]
}
}
如果需要查询大于15岁小于50的年龄
GET test3/_doc/_search
{
"query":{
"bool":{
"filter":{
"range":{
"age":{
"gt":15,
"lt":50
}
}
}
}
}
}
- gt:大于
- gte 大于等于
- lt 小于
- lte 小于等于
结果
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 0.0,
"hits" : [
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.0,
"_source" : {
"name" : "qwq",
"age" : 18,
"birth" : "2000-01-05"
}
},
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "3",
"_score" : 0.0,
"_source" : {
"name" : "阿巴阿巴",
"age" : 20,
"birth" : "2000-08-05"
}
}
]
}
}
也可以这样查询
GET test3/_doc/_search
{
"query":{
"match":{
"name":"qwq 张三"
}
}
}
结果
#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
"took" : 1,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 2,
"relation" : "eq"
},
"max_score" : 2.0834165,
"hits" : [
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "1",
"_score" : 2.0834165,
"_source" : {
"name" : "张三",
"age" : 13,
"birth" : "1997-01-05"
}
},
{
"_index" : "test3",
"_type" : "_doc",
"_id" : "2",
"_score" : 1.2800651,
"_source" : {
"name" : "qwq",
"age" : 18,
"birth" : "2000-01-05"
}
}
]
}
}
精确查询
term查询是通过倒排序所以指定的词条进行精确查找的
关于分词
term,直接精确查询的
match,会使用分词器解析
text会被分词解析,keyword不会
先插入测试数据
PUT testdb
{
"mappings": {
"properties": {
"name":{
"type":"text"
},
"desc":{
"type":"keyword"
}
}
}
}
PUT testdb/_doc/1
{
"name": "随意的java博客",
"desc":"随意的java世界"
}
PUT testdb/_doc/2
{
"name": "随意的php博客",
"desc":"随意的php世界"
}
测试请求
GET testdb/_search
{
"query":{
"term": {
"name": "随"
}
}
}
GET testdb/_search
{
"query":{
"term": {
"desc": "随"
}
}
}
第一个请求会返回
{
"took" : 0,
"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" : "随意的java博客",
"desc" : "随意的java世界"
}
},
{
"_index" : "testdb",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.18232156,
"_source" : {
"name" : "随意的php博客",
"desc" : "随意的php世界"
}
}
]
}
}
高亮查询
GET testdb/_search
{
"query":{
"term": {
"name": "随"
}
}
, "highlight": {
"pre_tags": "<p>", //自定义前缀
"post_tags": "</p>", //后缀
"fields": {
"name":{}
}
}
}
返回
{
"took" : 2,
"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" : "随意的java博客",
"desc" : "随意的java世界"
},
"highlight" : {
"name" : [
"<p>随</p>意的java博客"
]
}
},
{
"_index" : "testdb",
"_type" : "_doc",
"_id" : "2",
"_score" : 0.18232156,
"_source" : {
"name" : "随意的php博客",
"desc" : "随意的php世界"
},
"highlight" : {
"name" : [
"<p>随</p>意的php博客"
]
}
}
]
}
}