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


猜你喜欢
- IoC——Inversion of Control,控制反转在Java开发中,IoC意味着将你设计好的类交给系统去控制,而不是在你的类内部控
- 前言在上一篇普通的加载千篇一律,有趣的 loading 万里挑一 中,我们介绍了使用Path类的PathMetrics属性来控制绘制点在路径
- 使用方法 首先在Github或者Gitee上面新建一个仓库复制仓库的链接用idea在本地新建一个demo项目点击菜单栏的VCS,按
- 该说不唠,直接上代码。可直接复制使用package com.yuezhi.util;import java.math.BigDecimal;
- 一、数据输出SpringMVC将数据携带给页面的储存工具,有三种,map,ModelMap,model,它们在底层实质还是使用到了Bindi
- 我们与客户端的接 * 互中,为了更高的安全性,我们可能需要对接口加密(请求参数加密,服务端解密)、返回信息加密(服务端加密,客户端解密),但是
- JDBC Statement对象实例以下是利用以下三种查询以及打开和关闭说明的例子:boolean execute(String SQL)
- 之前已经为大家介绍过利用Java实现带GUI的气泡诗词特效,本文将为大家介绍另一种方法同样也可以实现气泡诗词的效果。下面是示例代码impor
- 定义建造者模式(Builder Pattern),又叫生成器模式,是一种对象构建模式 它可以将复杂对象的建造过程抽象出来,使这个抽象过程的不
- Maven中建立的依赖管理方式基本已成为Java语言依赖管理的事实标准,Maven的替代者Gradle也基本沿用了Maven的依赖管理机制。
- 背景在 Java 中实现线程安全的传统方式是 synchronized 关键字,虽然它提供了一定的同步能力,但它在使用上
- 话不多说,先看代码!/** * Created by david on 2017-7-5. */import com.google.gson
- 前言前几天有个需求,需要使用不同的数据源,例如某业务要用A数据源,另一个业务要用B数据源。我上网收集了一些资料整合了一下,虽然最后这个需求不
- AOP :面向切面编程在程序设计中,我们需要满足高耦合低内聚,所以编程需满足六大原则,一个法则.AOP面向切面编程正是为了满足这些原则的一种
- 本文介绍了浅谈Java的两种多线程实现方式,分享给大家。具有如下:一、创建多线程的两种方式Java中,有两种方式可以创建多线程:1 通过继承
- 文档中的设置有序或无序列表是一种反应内容上下级关系或者内容相同属性的方式,与单纯的文字叙述相比,它能有效增强文档内容的条理性,突出重点。因此
- * String类是不可变类,只要对String进行修改,都会导致新的对象生成。* StringBuffer和StringBuilder都是
- ScriptControl接口属性名称类型备注AllowUIBOOL检测是否允许运行用户的接口元素。如果为False,则诸如消息框之类的界面
- 一、引入先给出一个Num类的定义internal class Num{ public static int odd = 5000
- 最近学习了继承,多态,集合,设计模式,有一个汽车租凭系统,给大家分享一下:我们首先来看看我们这个系统的效果1.做一个项目,我们首先对项目进行