7、ElasticSearch的结构化查询

数据准备工作

文档数据mapping如下:

{
  "user" : {
    "mappings" : {
      "people" : {
        "properties" : {
          "age" : {
            "type" : "integer"
          },
          "hobby" : {
            "type" : "text",
            "analyzer" : "ik_max_word"
          },
          "mail" : {
            "type" : "keyword"
          },
          "name" : {
            "type" : "text"
          }
        }
      }
    }
  }
}

hobby字段使用了ik中文分词

文档数据如下:
在这里插入图片描述

1.1、term查询

查询某个字段里含有某个关键词的文档,对==查询关键词作为一个整体去查询 ==,主要用于搜索数字、日期、布尔值、未经分词的字符串

GET /user/_search
{
  "query": {
    "term": {
      "age": {
        "value": "21"
      }
    }
  }
} 
## 响应
{
  "took" : 59,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "people",
        "_id" : "hWk5jHQBzgrkYgRNOrUU",
        "_score" : 1.0,
        "_source" : {
          "name" : "李四",
          "age" : 21,
          "mail" : "222@qq.com",
          "hobby" : "羽毛球、乒乓球、足球、篮球"
        }
      }
    ]
  }
}
1.2、terms查询

与term查询相似,但terms允许指定多个匹配条件

举例:查询age=21,23的数据

GET /user/_search
{
  "query": {
    "terms": {
      "age": [
        "21",
        "23"
      ]
    }
  }
}
## 响应
{
  "took" : 262,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "people",
        "_id" : "hWk5jHQBzgrkYgRNOrUU",
        "_score" : 1.0,
        "_source" : {
          "name" : "李四",
          "age" : 21,
          "mail" : "222@qq.com",
          "hobby" : "羽毛球、乒乓球、足球、篮球"
        }
      },
      {
        "_index" : "user",
        "_type" : "people",
        "_id" : "h2k5jHQBzgrkYgRNOrUU",
        "_score" : 1.0,
        "_source" : {
          "name" : "赵六",
          "age" : 23,
          "mail" : "444@qq.com",
          "hobby" : "跑步、游泳、篮球"
        }
      }
    ]
  }
}
1.3、range查询

range允许我们按照指定范围去查找,如查找age在[21,23]之间的数据

GET /user/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 21,
        "lte": 23
      }
    }
  }
}
## 响应
{
  "took" : 85,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 3,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "people",
        "_id" : "hWk5jHQBzgrkYgRNOrUU",
        "_score" : 1.0,
        "_source" : {
          "name" : "李四",
          "age" : 21,
          "mail" : "222@qq.com",
          "hobby" : "羽毛球、乒乓球、足球、篮球"
        }
      },
      {
        "_index" : "user",
        "_type" : "people",
        "_id" : "hmk5jHQBzgrkYgRNOrUU",
        "_score" : 1.0,
        "_source" : {
          "name" : "王五",
          "age" : 22,
          "mail" : "333@qq.com",
          "hobby" : "羽毛球、篮球、游泳、听音乐"
        }
      },
      {
        "_index" : "user",
        "_type" : "people",
        "_id" : "h2k5jHQBzgrkYgRNOrUU",
        "_score" : 1.0,
        "_source" : {
          "name" : "赵六",
          "age" : 23,
          "mail" : "444@qq.com",
          "hobby" : "跑步、游泳、篮球"
        }
      }
    ]
  }
}

操作符包含以下

  • gt 大于
  • gte 大于等于
  • lt 小于
  • lte 小于等于
1.4、 match查询

match查询是一个标准查询,不管你需要全文本查询还是精确查询基本上都要用到它。

如果你使用match查询一个全文本字段,它会在真正查询之前用分析器先分析match一下查询字符。如果用match下指定了一个确切值,在遇到数字,日期,布尔值或者not_analyzed的字符串时,它将为你搜索你给定的值。

举例:查询爱好中包含篮球和音乐的数据

须知:下面的query 若没有operator,默认篮球与音乐是OR的关系

GET /user/_search
{
  "query": {
    "match": {
      "hobby": {
        "query": "篮球 音乐",
        "operator": "and"
      }
    }
  }
}
## 响应
{
  "took" : 9,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.7382001,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "people",
        "_id" : "hmk5jHQBzgrkYgRNOrUU",
        "_score" : 0.7382001,
        "_source" : {
          "name" : "王五",
          "age" : 22,
          "mail" : "333@qq.com",
          "hobby" : "羽毛球、篮球、游泳、听音乐"
        }
      }
    ]
  }
}
1.4.1、分页

分页涉及两个字段即from和size,from表示从哪条数据开始,size表示每页多少条数据。
from从0开始,默认返回10个结果。
获取靠后的数据,翻页成功较高

举例:分页查找(每页显示2条) 索引user中age大于20的数据

GET /user/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 20
      }
    }
  },
   "from":0,
   "size":2
}
## 响应
{
  "took" : 41,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 5,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "people",
        "_id" : "hGk5jHQBzgrkYgRNOrUU",
        "_score" : 1.0,
        "_source" : {
          "name" : "张三",
          "age" : 20,
          "mail" : "111@qq.com",
          "hobby" : "羽毛球、乒乓球、足球"
        }
      },
      {
        "_index" : "user",
        "_type" : "people",
        "_id" : "hWk5jHQBzgrkYgRNOrUU",
        "_score" : 1.0,
        "_source" : {
          "name" : "李四",
          "age" : 21,
          "mail" : "222@qq.com",
          "hobby" : "羽毛球、乒乓球、足球、篮球"
        }
      }
    ]
  }
}
1.4.2、排序
  • 最好在数字类型日期类型的字段上排序
  • 对于多值类型或分词分析过的字段排序,系统会选一个值,我们无法得知该值

举例:分页查找(每页显示2条) 索引user中age大于20的数据 并安装age倒序

GET /user/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 20
      }
    }
  },
   "from":0,
   "size":2,
   "sort": [
     {
       "age": {
         "order": "desc"
       }
     }
   ]
}
## 响应
{
  "took" : 57,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 5,
    "max_score" : null,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "people",
        "_id" : "iGk5jHQBzgrkYgRNOrUU",
        "_score" : null,
        "_source" : {
          "name" : "孙七",
          "age" : 24,
          "mail" : "555@qq.com",
          "hobby" : "听音乐、看电影、羽毛球"
        },
        "sort" : [
          24
        ]
      },
      {
        "_index" : "user",
        "_type" : "people",
        "_id" : "h2k5jHQBzgrkYgRNOrUU",
        "_score" : null,
        "_source" : {
          "name" : "赵六",
          "age" : 23,
          "mail" : "444@qq.com",
          "hobby" : "跑步、游泳、篮球"
        },
        "sort" : [
          23
        ]
      }
    ]
  }
}
1.4.3、_source 获取存储的原始数据

_source支持使用通配符,如_source[“name*”,“year”]。如果文档数据没有存储_source,那就只返回匹配文档的元数据

举例:取出索引user中id、name、hobby、abc字段

GET /user/_search
{
  "query": {
    "match_all": {}
  },
  "_source": ["age","name","hob*","abc"]
}
## 响应
{
    "took": 5,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": 5,
        "max_score": 1,
        "hits": [
            {
                "_index": "user",
                "_type": "people",
                "_id": "hGk5jHQBzgrkYgRNOrUU",
                "_score": 1,
                "_source": {
                    "name": "张三",
                    "age": 20,
                    "hobby": "羽毛球、乒乓球、足球"
                }
            },
            {
                "_index": "user",
                "_type": "people",
                "_id": "hWk5jHQBzgrkYgRNOrUU",
                "_score": 1,
                "_source": {
                    "name": "李四",
                    "age": 21,
                    "hobby": "羽毛球、乒乓球、足球、篮球"
                }
            },
            {
                "_index": "user",
                "_type": "people",
                "_id": "iGk5jHQBzgrkYgRNOrUU",
                "_score": 1,
                "_source": {
                    "name": "孙七",
                    "age": 24,
                    "hobby": "听音乐、看电影、羽毛球"
                }
            },
            {
                "_index": "user",
                "_type": "people",
                "_id": "hmk5jHQBzgrkYgRNOrUU",
                "_score": 1,
                "_source": {
                    "name": "王五",
                    "age": 22,
                    "hobby": "羽毛球、篮球、游泳、听音乐"
                }
            },
            {
                "_index": "user",
                "_type": "people",
                "_id": "h2k5jHQBzgrkYgRNOrUU",
                "_score": 1,
                "_source": {
                    "name": "赵六",
                    "age": 23,
                    "hobby": "跑步、游泳、篮球"
                }
            }
        ]
    }
}

由于文档中不存在abc列,所以响应里并未展示该列

1.4.4、脚本字段

对源数据进行修饰并展示出去
举例:将索引user中age=20的数据中age字段添上"岁" 并输出

GET /user/_search
{
  "query": {
    "match": {
      "age": "20"
    }
  },
  "script_fields": {
    "age": {
      "script": {
        "lang": "painless",
        "source":"doc['age'].value+'岁'"
      }
    }
  }
}
## 响应
{
  "took" : 6,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "people",
        "_id" : "hGk5jHQBzgrkYgRNOrUU",
        "_score" : 1.0,
        "fields" : {
          "age" : [
            "20岁"
          ]
        }
      }
    ]
  }
}
1.5、bool查询

bool查询是用来合并多个条件查询结果的布尔逻辑,它包含以下操作符:

  • must 多个查询条件的完全匹配,相当于AND
  • must_not 多个查询条件的相反匹配 相当于NOT
  • should 其中的查询条件至少有一个会匹配,相当于OR

这些参数可以分别集成一个查询条件或多个查询条件的数据

举例:查询爱好中包含篮球,不包含音乐的,年龄是21~23之间的数据

GET /user/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "hobby": "篮球"
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "hobby": "音乐"
          }
        }
      ],
      "should": [
        {
          "terms": {
            "age": [
              "21",
              "22",
              "23"
            ]
          }
        }
      ]
    }
  }
}
## 响应
{
  "took" : 46,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 1.287682,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "people",
        "_id" : "hWk5jHQBzgrkYgRNOrUU",
        "_score" : 1.287682,
        "_source" : {
          "name" : "李四",
          "age" : 21,
          "mail" : "222@qq.com",
          "hobby" : "羽毛球、乒乓球、足球、篮球"
        }
      },
      {
        "_index" : "user",
        "_type" : "people",
        "_id" : "h2k5jHQBzgrkYgRNOrUU",
        "_score" : 1.2239686,
        "_source" : {
          "name" : "赵六",
          "age" : 23,
          "mail" : "444@qq.com",
          "hobby" : "跑步、游泳、篮球"
        }
      }
    ]
  }
}
1.5.1、过滤查询

查询年龄是21岁的用户数据

GET /user/_search
{
  "query": {
    "bool": {
      "filter": {
        "term": {
          "age": "21"
        }
      }
    }
  }
}
## 响应
{
  "took" : 29,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.0,
    "hits" : [
      {
        "_index" : "user",
        "_type" : "people",
        "_id" : "hWk5jHQBzgrkYgRNOrUU",
        "_score" : 0.0,
        "_source" : {
          "name" : "李四",
          "age" : 21,
          "mail" : "222@qq.com",
          "hobby" : "羽毛球、乒乓球、足球、篮球"
        }
      }
    ]
  }
}
1.6、短语搜索 Match Phrase

就像match查询对于标准全文搜索是一种最常用的查询一样,当你想找到彼此邻近搜索词时,就会想到match_phrase查询

举例:搜索 title包含"Beautiful Mind"的数据
语法示例如下:

GET /movies/_search
{
  "query": {
   "match_phrase": {
     "title":"Beautiful Mind"
   }
  }
}

类似 match 查询, match_phrase 查询首先将查询字符串解析成一个词项列表,然后对这些词项进行搜索,但只保留那些包含 全部 搜索词项,且 位置 与搜索词项相同的文档,且中间不许夹杂其他词,即 Beautiful 在前,Mind在后,Mind紧挨Beautiful

有时候,搜索词不是紧挨着的,如果仍需要可以搜索匹配到,这就需要使用slop了,slop表示搜索词项相隔多远时 仍可匹配

举例:查询title包含"Beautiful Mind"的数据,搜索词项可相隔1个位置

GET /movies/_search
{
  "query": {
   "match_phrase": {
     "title":{
       "query": "Beautiful Mind",
       "slop": 1
     }
   }
  }
}
## 响应
{
  "took" : 13,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 1,
    "max_score" : 0.37229446,
    "hits" : [
      {
        "_index" : "movies",
        "_type" : "test",
        "_id" : "1",
        "_score" : 0.37229446,
        "_source" : {
          "title" : "Beautiful A,Mind"
        }
      }
    ]
  }
}

1.7、Query String 查询

创建一个索引及数据来模拟此种查询

POST people/qry/1
{
  "name":"ta jiushiwo",
  "age":24
}

POST people/qry/2
{
  "name":"wo jiushiwo",
  "age":24
}

查询可以使用AND、OR

举例:查询 name中包含了"wo"或者"ta"的数据

GET people/_search
{
  "query": {
    "query_string": {
      "default_field": "name",
      "query": "wo OR ta"
    }
  }
}
## 响应
{
  "took" : 3,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "people",
        "_type" : "qry",
        "_id" : "2",
        "_score" : 0.2876821,
        "_source" : {
          "name" : "wo jiushiwo",
          "age" : 24
        }
      },
      {
        "_index" : "people",
        "_type" : "qry",
        "_id" : "1",
        "_score" : 0.2876821,
        "_source" : {
          "name" : "ta jiushiwo",
          "age" : 24
        }
      }
    ]
  }
}

举例:查询 name中包含 “wo"或者"ta” 且 包含”jiushiwo“的数据

GET people/_search
{
  "query": {
    "query_string": {
      "default_field": "name",
      "query": "(wo OR ta) and jiushiwo"
    }
  }
}
## 响应
{
  "took" : 15,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.5753642,
    "hits" : [
      {
        "_index" : "people",
        "_type" : "qry",
        "_id" : "2",
        "_score" : 0.5753642,
        "_source" : {
          "name" : "wo jiushiwo",
          "age" : 24
        }
      },
      {
        "_index" : "people",
        "_type" : "qry",
        "_id" : "1",
        "_score" : 0.5753642,
        "_source" : {
          "name" : "ta jiushiwo",
          "age" : 24
        }
      }
    ]
  }
}
1.8、Simple Query String 查询
  • 类似Query String,但会忽略错误的语法,同时只支持部分查询语法
  • 不支持AND/OR/NOT,会把这些当做字符串处理
  • Term之间默认的关系是OR,可以指定Operator

以下符号可以替代AND/OR/NOT

  • +替代 AND
  • | 替代 OR
  • - 替代 NOT

举例:查询索引user中name同时包含"wo"、"ta"的数据

GET people/_search
{
  "query": {
    "simple_query_string": {
      "query": "wo +ta",
      "fields": ["name"]
    }
  }
}
## 响应
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 0,
    "max_score" : null,
    "hits" : [ ]
  }
}

举例:查询索引user中name包含"wo"或"ta"的数据

GET people/_search
{
  "query": {
    "simple_query_string": {
      "query": "wo|ta",
      "fields": ["name"]
    }
  }
}
## 响应
{
  "took" : 11,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 2,
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "people",
        "_type" : "qry",
        "_id" : "2",
        "_score" : 0.2876821,
        "_source" : {
          "name" : "wo jiushiwo",
          "age" : 24
        }
      },
      {
        "_index" : "people",
        "_type" : "qry",
        "_id" : "1",
        "_score" : 0.2876821,
        "_source" : {
          "name" : "ta jiushiwo",
          "age" : 24
        }
      }
    ]
  }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值