软件编程
位置:首页>> 软件编程>> java编程>> ElasticSearch查询文档基本操作实例

ElasticSearch查询文档基本操作实例

作者:程序员皮卡秋  发布时间:2023-11-24 14:20:02 

标签:ElasticSearch,查询文档

查询文档 & 基本操作

为了方便学习, 本节中所有示例沿用上节的索引

按照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中通过参数sizefrom来进行基础分页的控制

  • 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

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com