前面说的URI的搜索方式,实际上我们开发中不是很常用,我们更常用的是一种叫做request body的查询方式,也就是DSL查询语句。
一、Request Body Search
这种方式也就是DSL,其操作就是把查询语句通过HTTP Request Body发送方给ES,很多高阶使用方法只能在DSL中使用。
1、基本语法
基本查询
POST /movies/_search?ignore_unavailable=true
{
"profile": "true",
"query": {
"match_all": {}
}
}
这是一个基本的查询语句,我们开启了profile展示详情查询,然后查询方式是match_all查询所有的文档。
分页
POST /kibana_sample_data_ecommerce/_search
{
"from": 10,
"size": 20,
"query": {
"match_all": {}
}
}
我们查询指定索引的分页记录,from在es中是从0开始的,默认是返回10个结果。
这里我们是从10开始,查询20条记录。
当然了ES也存在深分页问题。
排序
POST /kibana_sample_data_ecommerce/_search
{
"sort": [
{
"order_date": {
"order": "desc"
}
}
],
"from": 10,
"size": 20,
"query": {
"match_all": {}
}
}
分页,并且对结果进行按照order_date的desc排序。
对于排序来说,最好是在数字型和日期型的字段上进行排序,因为对于多值类型或者分析过的字段排序,es会选一个值,无法得知该值。这里存疑,后面验证一下。
_source filtering
上面我们的查询都是查询回来的所有的文档字段,有时候你的查询结果是不需要有些字段的,所以可以指定你要查询的结果里面有哪些属性。
POST /kibana_sample_data_ecommerce/_search
{
"_source": ["order_date"],
"from": 10,
"size": 20,
"query": {
"match_all": {}
}
}
我们这里就查了一个字段order_date,要是你的_source里面没有存储这个字段,那你查出来的就是文档的元数据,其他的没信息。
_source也支持通配符的查询_source["name*","desc*"]
"hits" : [
{
"_index" : "kibana_sample_data_ecommerce",
"_type" : "_doc",
"_id" : "RKOM1oEBYdLA1Zb4Ka7u",
"_score" : 1.0,
"_source" : {
"order_date" : "2022-07-12T09:43:12+00:00" 只返回一个
}
},
]
脚本字段
DSL中可以按照painless脚本来结合其他字段计算出一个新的结果作为查询返回。
例子:订单中有不同的汇率,需要结合汇率对订单进行排序。
POST /kibana_sample_data_ecommerce/_search
{
"script_fields": {
"new_field_lyx": { 给我们的结果命名为new_field
"script": {
"lang": "painless",
"source": "doc['order_date'].value + 'hello'"
}
}
},
"from": 10,
"size": 20,
"query": {
"match_all": {}
}
}
我们指定了painless脚本,把order_date订单下单日期和hello结合起来了。
查询结果如下:
"hits" : [
{
"_index" : "kibana_sample_data_ecommerce",
"_type" : "_doc",
"_id" : "_KOM1oEBYdLA1Zb4OLn0",
"_score" : 1.0,
"fields" : { 脚本查询的结果再这里显示
"new_field_lyx" : [
"2022-07-02T10:48:00.000Zhello"
]
}
}
]
使用查询表达式-Match
POST /movies/_search
{
"query": {
"match": {
"title": "Road to Utopia"
}
}
}
普通的match查询,指定字段,这种他是分词之后查的其实是Road OR to OR Utopia
三个词随便出来一个匹配的就行。
要想做成三个同时匹配的需要加操作如下:
POST /movies/_search
{
"query": {
"match": {
"title":{
"query": "Road to Utopia",
"operator": "and" 这一行标识查询的时候三个都匹配才行,而且不区分顺序
}
}
}
}
短语搜索-Match Phrase
上面那种是分词之后按照词匹配的,这种是直接搜语句。
POST /movies/_search
{
"query": {
"match_phrase": {
"title":{
"query": "Road to Utopia"
}
}
}
}
这种匹配出来的只能是包含Road to Utopia这个语句的,而且严格词汇顺序,中间不能有插入别的字段的。
POST /movies/_search
{
"query": {
"match_phrase": {
"title":{
"query": "Road Utopia",
"slop": 1
}
}
}
}
"slop": 1表示你不需要完全按照这个语句匹配,中间插入一个字符也能被匹配到
举个例子,你不加这个你查“我你”,这时候我爱你是查不出来的。但是你加了"slop": 1这时候就允许中间出一个字,我爱你就能查到了,但是我很爱你不行,因为他加了两个字。
二、总结
查询语法很基本,但是掌握扎实,后面才能灵活应用。其实复杂的DSL最好还是别写,设计好点规避复杂查询。