ElasticSearch查询文档基本操作实例
作者:程序员皮卡秋 发布时间:2023-11-24 14:20:02
查询文档 & 基本操作
为了方便学习, 本节中所有示例沿用上节的索引
按照ID单个
GET class_1/_doc/1
查询结果:
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "1",
"_version" : 4,
"_seq_no" : 4,
"_primary_term" : 3,
"found" : true,
"_source" : {
"name" : "l",
"num" : 6
}
}
按照ID批量
GET class_1/_mget
{
"ids":[1,2,3]
}
返回:
{
"docs" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "1",
"_version" : 4,
"_seq_no" : 4,
"_primary_term" : 3,
"found" : true,
"_source" : {
"name" : "l",
"num" : 6
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "2",
"found" : false
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "3",
"_version" : 3,
"_seq_no" : 10,
"_primary_term" : 4,
"found" : true,
"_source" : {
"num" : 9,
"name" : "e",
"age" : 9,
"desc" : [
"hhhh"
]
}
}
]
}
查询文档是否存在 & 通过id判断
HEAD class_1/_doc/1
返回:
200 - OK
HEAD class_1/_doc/1000
返回:
404 - Not Found
查询部分字段内容
GET class_1/_doc/1?_source_includes=name
返回:
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "1",
"_version" : 4,
"_seq_no" : 4,
"_primary_term" : 3,
"found" : true,
"_source" : {
"name" : "l"
}
}
可以看到只返回了name
字段, 以上是一个基本的操作,下面给大家讲下条件查询~
查询文档 & 条件查询
查询的复杂度取决于它附加的条件约束,跟我们写sql
一样。下面就带大家一步一步看一下ES
中如何进行条件查询~
不附加任何条件
GET class_1/_search
返回:
{
"took" : 15,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 8,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "h2Fg-4UBECmbBdQA6VLg",
"_score" : 1.0,
"_source" : {
"name" : "b",
"num" : 6
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "iGFt-4UBECmbBdQAnVJe",
"_score" : 1.0,
"_source" : {
"name" : "g",
"age" : 8
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "iWFt-4UBECmbBdQAnVJg",
"_score" : 1.0,
"_source" : {
"name" : "h",
"age" : 9
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "imFt-4UBECmbBdQAnVJg",
"_score" : 1.0,
"_source" : {
"name" : "i",
"age" : 10
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"num" : 9,
"name" : "e",
"age" : 9,
"desc" : [
"hhhh"
]
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "4",
"_score" : 1.0,
"_source" : {
"name" : "f",
"age" : 10,
"num" : 10
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "RWlfBIUBDuA8yW5cu9wu",
"_score" : 1.0,
"_source" : {
"name" : "一年级",
"num" : 20
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"name" : "l",
"num" : 6
}
}
]
}
}
可以看到索引class_1
中的所有数据都是上节添加的。这里提一下,我们也可以添加多个索引一起查,然后返回,用,逗号
隔开就可以了
GET class_1,class_2,class_3/_search
{
"took" : 7,
"timed_out" : false,
"_shards" : {
"total" : 5,
"successful" : 5,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 9,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "h2Fg-4UBECmbBdQA6VLg",
"_score" : 1.0,
"_source" : {
"name" : "b",
"num" : 6
}
},
{
"_index" : "class_2",
"_type" : "_doc",
"_id" : "RWlfBIUBDuA8yW5cu9wu",
"_score" : 1.0,
"_source" : {
"name" : "一年级",
"num" : 20
}
},
....
]
}
}
可以看到返回了索引class_2
中的数据,并且合并到了一起。
相关字段解释
有的小伙伴可能对返回的字段有点陌生,这里给大家统一解释一下:
{
"took":"查询操作耗时,单位毫秒",
"timed_out":"是否超时",
"_shards":{
"total":"分片总数",
"successful":"执行成功分片数",
"skipped":"执行忽略分片数",
"failed":"执行失败分片数"
},
"hits":{
"total":{
"value":"条件查询命中数",
"relation":"计数规则(eq计数准确/gte计数不准确)"
},
"max_score":"最大匹配度分值",
"hits":[
{
"_index":"命中结果索引",
"_id":"命中结果ID",
"_score":"命中结果分数",
"_source":"命中结果原文档信息"
}
]
}
}
下面我们看下带条件的查询~
基础分页查询
基本语法: es
中通过参数size
和from
来进行基础分页
的控制
from
:指定跳过
多少条数据size
:指定返回
多少条数据
下面看下示例:
url参数
GET class_1/_search?from=2&size=2
返回:
{
"took" : 5,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 8,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "iWFt-4UBECmbBdQAnVJg",
"_score" : 1.0,
"_source" : {
"name" : "h",
"age" : 9
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "imFt-4UBECmbBdQAnVJg",
"_score" : 1.0,
"_source" : {
"name" : "i",
"age" : 10
}
}
]
}
}
body 参数
GET class_1/_search
{
"from" : 2,
"size" : 2
}
返回结果和上面是一样的~
单字段全文索引查询
这个大家应该不陌生,前面几节都见过。使用query.match
进行查询,match
适用与对单个字段基于全文索引进行数据检索。对于全文字段,match
使用特定的分词
进行全文检索。而对于那些精确值,match
同样可以进行精确匹配,match
查询短语时,会对短语进行分词,再针对每个词条进行全文检索。
GET class_1/_search
{
"query": {
"match": {
"name":"i"
}
}
}
返回:
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.3862942,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "imFt-4UBECmbBdQAnVJg",
"_score" : 1.3862942,
"_source" : {
"name" : "i",
"age" : 10
}
}
]
}
}
单字段不分词查询
使用query.match_phrase
进行查询, 它与match
的区别就是不进行分词,干说,可能有点抽象,下面我们通过一个例子给大家分清楚:
先造点数据进去:
PUT class_1/_bulk
{ "create":{ } }
{"name":"I eat apple so haochi1~","num": 1}
{ "create":{ } }
{ "name":"I eat apple so zhen haochi2~","num": 1}
{ "create":{ } }
{"name":"I eat apple so haochi3~","num": 1}
假设有这么几个句子,现在我有一个需求我要把I eat apple so zhen haochi2~
这句话匹配出来
match分词结果
GET class_1/_search
{
"query": {
"match": {
"name": "apple so zhen"
}
}
}
返回:
{
"took" : 15,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 2.2169428,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "cMfcCoYB090miyjed7YE",
"_score" : 2.2169428,
"_source" : {
"name" : "I eat apple so zhen haochi2~",
"num" : 1
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "b8fcCoYB090miyjed7YE",
"_score" : 1.505254,
"_source" : {
"name" : "I eat apple so haochi1~",
"num" : 1
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "ccfcCoYB090miyjed7YE",
"_score" : 1.505254,
"_source" : {
"name" : "I eat apple so haochi3~",
"num" : 1
}
}
]
}
}
从结果来看,刚刚的几句话都被查出来了,但是结果并大符合预期。从score
来看,"_score" : 2.2169428
得分最高,排在了第一,语句是I eat apple so zhen haochi2~
,说明匹配度最高,这个句子正是我们想要的结果~
match_phrase 不分词查询结果
GET class_1/_search
{
"query": {
"match_phrase": {
"name": "apple so zhen"
}
}
}
结果:
{
"took" : 6,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 2.2169428,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "cMfcCoYB090miyjed7YE",
"_score" : 2.2169428,
"_source" : {
"name" : "I eat apple so zhen haochi2~",
"num" : 1
}
}
]
}
}
结果符合预期,只返回了我们想要的那句。那么match
为什么都返回了,这就是前面讲到的分词
,首先会对name: apple so zhen
进行分词,也就是说存在apple
的都会被返回。
当然,真正业务中的需求比这个复杂多了,这里只是为了给大家做区分~ 下面接着看~
多字段全文索引查询
相当于对多个字段执行了match
查询, 这里需要注意的是query
的类型要和字段类型一致,不然会报类型异常
GET class_1/_search
{
"query": {
"multi_match": {
"query": "apple",
"fields": ["name","desc"]
}
}
}
{
"took" : 5,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 0.752627,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "b8fcCoYB090miyjed7YE",
"_score" : 0.752627,
"_source" : {
"name" : "I eat apple so haochi1~",
"num" : 1
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "ccfcCoYB090miyjed7YE",
"_score" : 0.752627,
"_source" : {
"name" : "I eat apple so haochi3~",
"num" : 1
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "cMfcCoYB090miyjed7YE",
"_score" : 0.7389809,
"_source" : {
"name" : "I eat apple so zhen haochi2~",
"num" : 1
}
}
]
}
}
范围查询
使用range
来进行范围查询,适用于数组
,时间
等字段
GET class_1/_search
{
"query": {
"range": {
"num": {
"gt": 5,
"lt": 10
}
}
}
}
返回:
{
"took" : 6,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 3,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "h2Fg-4UBECmbBdQA6VLg",
"_score" : 1.0,
"_source" : {
"name" : "b",
"num" : 6
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"num" : 9,
"name" : "e",
"age" : 9,
"desc" : [
"hhhh"
]
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"_source" : {
"name" : "l",
"num" : 6
}
}
]
}
}
单字段精确查询
使用term
进行非分词字段
的精确查询。需要注意的是,对于那些分词的字段,即使查询的value
是一个完全匹配的短语,也无法完成查询
GET class_1/_search
{
"query": {
"term": {
"num": {
"value": "9"
}
}
}
}
返回:
{
"took" : 4,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"num" : 9,
"name" : "e",
"age" : 9,
"desc" : [
"hhhh"
]
}
}
]
}
}
字段精确查询 & 多值
与term一样, 区别在于可以匹配一个字段的多个值,满足一个即检索成功
GET class_1/_search
{
"query": {
"terms": {
"num": [
9,
1
]
}
}
}
返回:
{
"took" : 8,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 4,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"num" : 9,
"name" : "e",
"age" : 9,
"desc" : [
"hhhh"
]
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "b8fcCoYB090miyjed7YE",
"_score" : 1.0,
"_source" : {
"name" : "I eat apple so haochi1~",
"num" : 1
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "ccfcCoYB090miyjed7YE",
"_score" : 1.0,
"_source" : {
"name" : "I eat apple so haochi3~",
"num" : 1
}
},
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "cMfcCoYB090miyjed7YE",
"_score" : 1.0,
"_source" : {
"name" : "I eat apple so zhen haochi2~",
"num" : 1
}
}
]
}
}
文档包含字段查询
为了确定当前索引有哪些文档包含了对应的字段,es
中使用exists
来实现
GET class_1/_search
{
"query": {
"exists": {
"field": "desc"
}
}
}
返回:
{
"took" : 8,
"timed_out" : false,
"_shards" : {
"total" : 3,
"successful" : 3,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "class_1",
"_type" : "_doc",
"_id" : "3",
"_score" : 1.0,
"_source" : {
"num" : 9,
"name" : "e",
"age" : 9,
"desc" : [
"hhhh"
]
}
}
]
}
}
结束语
本节主要讲了ES
中的文档查询API操作,该部分内容较多, 下节继续给大家讲,就先消化这么多~API
大家都不要去背,多敲几遍就记住了,关键是多用,多总结 。
来源:https://juejin.cn/post/7195023863489511483
猜你喜欢
- 引言备忘录模式经常可以遇到,譬如下面这些场景:浏览器回退:浏览器一般有浏览记录,当我们在一个网页上点击几次链接之后,可在左上角点击左箭头回退
- 请求SpringBoot接受前台参数的六种方式,首先因为从前台发送的请求没有界面的话只能是从地址栏发送并且只能是Get请求,为了测试其他的请
- java中String、StringBuffer、StringBuilder是编程中经常使用的字符串类,他们之间的区别也是经常在面试中会问到
- Java 判断字符串中是否包含中文的实例详解 Java判断一个字符串是否有中文是利用Unicode编码来判断,因为中
- 前言之前我们提到了 CustomPaint er 的 Paint 可以使用渐变(GradientShader)来填充绘制的图形,本篇我们来介
- 本文实例总结了MFC程序设计常用技巧。分享给大家供大家参考。具体如下:1.属性页的添加:创建对话框的类,该类要从CpropertyPage继
- 1、原理事务的概念想必大家都很清楚,其ACID特性在开发过程中占有重要的地位。同时在并发过程中会出现一些一致性问题,为了解决一致性问题,也出
- 昨天在与对端系统调接口的时候,对端系统对我们传过去的json串老是处理不了,后来查原因是应为我们传过去的json串里有json对象数组,因为
- 简单几步,实现SpringMVC+servlet3.0文件上传功能:第一步:配置web.xml文件中的servlet,添加multipart
- 1 配置多数据源时,application.yml 的有关mybatis的配置是失效的,因为他不知道配置哪一个数据源2 applicatio
- 1.用途在SpringBoot中,通过jasypt可以进行加密解密. 这个是双向的, 且可以配置密钥.2.使用:2.1通过UT创建工具类,并
- 项目结构项目路径可以自己定义,只要路径映射正确就可以pom.xml <properties> <spring.versio
- 前言回调的核心就是回调方将本身即this传递给调用方,这样调用方就可以在调用完毕之后告诉回调方它想要知道的信息。1、什么是回调软件模块之间总
- 序言之前封装过一个日志注解,打印方法执行信息,功能较为单一不够灵活,近来兴趣来了,想重构下,使其支持表达式语法,以应对灵活的日志打印需求。该
- 概述: 当希望能直接在数据库语言中只检索符合条件的记录,不需要再通过程序对其做处理时,SQL语句分页
- 本文实例为大家分享了android自定义环形对比图的具体代码,供大家参考,具体内容如下1.首先在res/values里创建一个attr.xm
- 一、使用Optional引言1.1、代码问题引出在写程序的时候一般都遇到过 NullPointerException,所以经常会对程序进行非
- 本文实例为大家分享了java实现简单斗地主的具体代码,供大家参考,具体内容如下第一种方法 /** * @param args */ /**
- 在 Java 中,所有的异常都有一个共同的祖先 Throwable(可抛出)。Throwable 指定代码中可用异常传播机制通过 Java
- 工厂方法模式(Factory Method):定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。工