1. 测试数据准备
官方GitHub有给我们提供测试数据,https://github.com/elastic/elasticsearch/edit/master/docs/src/test/resources/accounts.json
进入,将数据复制,然后在Kibana上执行批量操作,如图:
查看索引信息
API官网参考地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/getting-started-search.html
以下内容均可在上面API官网参考地址中找到出处
2. Search API
ES支持两种基本检索方式:
1)通过使用Rest request url 发送搜索参数(uri + 检索参数)
2)通过REST request body 来发送它们(uri + 请求体)
2.1 检索信息
一切检索从 _search 开始
GET bank/_search | 检索 bank 下所有的信息,包括type和docs |
GET bank/_search?q=*&sort=account_number:asc | 请求参数方式检索 |
响应结果解释: took:ElasticSearch执行搜索的时间,单位毫秒 timed_out:搜索是否超时 _shards:告诉我们多少个分片被搜索了,以及统计了成功/失败的搜索分片 hits:搜索结果 hits.total:搜索结果 hits.hits:实际的搜索结果数组(默认为前10的文档) sort:搜索结果的排序key(键)(没有则按照score排序) score和max_score:相关性得分和最高分(全文检索用) |
2.1.1 检索所有
例如:
GET bank/_search
2.1.2 请求参数方式检索
例如:
GET bank/_search?q=*&sort=account_number:asc
参数解释:
GET:表示发送get请求
bank:表示索引
_search:固定写法
q=* :表示查询所有
sort=account_number:asc:表示查询结果按照account_number字段升序排序
2.2 uri + 请求体检索
例如:
GET bank/_search
{
"query":{
"match_all":{}
},
"sort":[
{
"account_number":{
"order":"desc"
}
}
]
}
参数解释:
1) GET bank/_search:表示get请求bank索引下的数据
2)query:表示查询条件,match_all表示匹配所有,规则有就写,没有就写一个大括号{}
3)sort:表示排序规则,上面写法也可以改成如下形式
GET bank/_search
{
"query":{
"match_all":{}
},
"sort":[
{
"account_number":"desc"
}
]
}
搜索结果如图:
注意:postman中,get请求不能携带请求体,我们可以将get请求改成一个json风格的post查询请求体到 _search API。一旦搜索的结果被返回,ElasticSearch就完成了这次请求,并且不会维护任何服务端的资源或者结果的cursor(游标)
3. Query DSL
语法参考地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html
3.1 基本语法格式
ElasticSearch提供了一个可以执行查询的json风格的DSL(domain-specific language 领域特定语言)。这个被称之为Query DSL。该查询语言非常全面,并且刚开始的时候感觉有点复杂,之后我们的查询几乎都是使用该种方式进行
例如:上面的 uri + 请求体检索 就是一个Query DSL查询
3.1.1 典型语法解构
{
QUERY_NAME:{
ARGUMENT:VALUE,
ARGUMENT:VALUE, ... ...
}
}
3.1.2 针对具体字段的查询
{
QUERY_NAME:{
FIELD_NAME:{
ARGUMENT:VALUE,
ARGUMENT:VALUE,
}
}
}
3.2 常见的argument
1)query:定义如何查询
2)match_all:查询类型,代表查询所有。
注意:es中可以在query中组合非常多的查询类型完成复杂查询
3)form + size 限定,可以完成分页查询功能
4)sort:排序。多个字段排序,会在前序字段相等时,后续字段内部排序,否则以前序为准
5)_source:指定需要返回的字段
例如:
GET bank/_search
{
"query": {
"match_all": {}
},
"from": 0,
"size": 3,
"sort": [
{
"account_number": "desc"
}
],
"_source": "firstname"
}
注意:如果要返回多个字段,需要用数组,如图:
返回结果如图:
3.3 match 全文检索匹配查询
前面我们在query中使用了match_all来查询所有,现在我们使用math来查询指定的值。
全文检索按照评分进行排序,会对检索条件进行分词匹配,并计算匹配结果得分_score
语法:
GET bank/_search
{
"query":{
"match": {
"FIELD": "TEXT"
}
}
}
3.3.1 基本类型(非字符串),精确匹配
匹配account_number=20的用户
GET bank/_search
{
"query":{
"match": {
"account_number": "20"
}
}
}
搜索结果如图:
3.3.2 字符串,全文检索
1)查询出address中包含Kings的所有记录
GET bank/_search
{
"query":{
"match": {
"address": "Kings"
}
}
}
搜索结果如图:
match当搜索字符串类型的时候,会进行全文检索,并且每条记录都要相关性得分
2)字符串,多个单词(分词+全文检索)
GET bank/_search
{
"query":{
"match": {
"address": "mill road"
}
}
}
如图:
最终查询出address中包含mill或者road或者mill road的所有记录,并给出相关性得分
3.4 match_phrase短语匹配
将需要匹配的值当成一个整体单词(不分词)进行检索
语法:
GET bank/_search
{
"query":{
"match_phrase": {
"FIELD": "PHRASE"
}
}
}
例如:查询address中包含mill road的所有记录,并给出相关性得分
GET bank/_search
{
"query":{
"match_phrase": {
"address": "mill road"
}
}
}
短语匹配也可以使用match+keyword关键字查询
例如;
GET bank/_search
{
"query":{
"match": {
"address.keyword": "990 Mill Road"
}
}
}
查询结果:
注意:match+keyword与match_phrase短语匹配的区别是,match_phrase短语匹配可以匹配包含关系,但是match+keyword只能全包也就是精确查询,例如上面的例子,将"990 Mill Road"替换成"Mill Road"使用match+keyword就匹配不到
3.5 multi_match多字段匹配
语法:
GET bank/_search
{
"query": {
"multi_match": {
"query": "",
"fields": []
}
}
}
例如:查询state和address中包含mill的用户
GET bank/_search
{
"query":{
"multi_match": {
"query": "mill",
"fields": ["state","address"]
}
}
}
结果如图:
注意:如果query查询内容包含多个单词,也会进行分词
3.6 bool复合查询
bool复合查询有四个条件值可供组装 must、must_not、should、filter
3.6.1 must/must_not
必须是与必须不是指定的情况
例如1:查询age=38且lastname=Small的用户
GET /bank/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"age": "38"
}
},
{
"match": {
"lastname": "Small"
}
}
]
}
}
}
查询结果:
例如2:查询age=38且lastname=Small,且firstname不等于White的用户
GET /bank/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"age": "38"
}
},
{
"match": {
"lastname": "Small"
}
}
],
"must_not": [
{
"match": {
"firstname": "White"
}
}
]
}
}
}
例如3:查询年龄在18-30之间的用户
使用range
GET /bank/_search
{
"query": {
"bool": {
"must": [
{
"range": {
"age": {
"gte": 18,
"lte": 30
}
}
}
]
}
}
}
查询结果如图:
3.6.2 should
应该达到should列举的条件,如果达到会增加相文档的评分,并不会改变查询结果。如果query只有should且只有一种匹配规则,那么should的条件就会被视作默认匹配条件而去改变查询结果
例如:查询年龄必须等于38且地址必须包含mill并且firstname应该=Parker的用户
GET /bank/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"age": "38"
}
},
{
"match": {
"address": "mill"
}
}
],
"should": [
{
"match": {
"firstname": "Parker"
}
}
]
}
}
}
查询结果;
可以发现,当满足should的条件的时候,相关性得分就比较高
3.6.3 filter结果过滤
并不是所有的查询都需要产生分数,特别是那些仅用于filtering(过滤)的文档,为了不计算分数,ES会自动检查场景并且优化查询的执行,也就是使用filter检索,不会贡献相关性得分。
注意:must_not是一种filter,所以must_not的匹配也不会贡献相关性得分
例如:使用filter代替must查询age在18-30之间的用户
GET /bank/_search
{
"query": {
"bool": {
"filter": [
{
"range": {
"age": {
"gte": 18,
"lte": 30
}
}
}
]
}
}
}
查询结果如图,相关性得分都为0.0,证明filter检索不贡献文档相关性得分
3.7 term
和match一样,匹配某个属性的值,全文检索字段用match,其他非text字段匹配用term,也就是term适用于精确匹配
例如;查询年龄=28的用户
GET /bank/_search
{
"query": {
"term": {
"age": 28
}
}
}
查询结果如图;
3.8 嵌入式属性查询nested
嵌入式的属性其心态类似于List<Attrs> attrs这样的格式的,在es中存储的格式如下图所示:
该格式的数据,无法通过普通的查询来获取到查询结果因为es会对嵌入式的数据进行扁平化处理,如:
3.8.1 语法格式
详情参看官网介绍:https://www.elastic.co/guide/en/elasticsearch/reference/7.5/query-dsl-nested-query.html
1)存储语法格式
PUT /my_index
{
"mappings" : {
"properties" : {
"obj1" : {
"type" : "nested"
}
}
}
}
2)查询语法格式
GET /my_index/_search
{
"query": {
"nested" : {
"path" : "obj1",
"query" : {
"bool" : {
"must" : [
{ "match" : {"obj1.name" : "blue"} },
{ "range" : {"obj1.count" : {"gt" : 5}} }
]
}
},
"score_mode" : "avg"
}
}
}
注意:
1)path就是嵌入式属性的名称,如图:
2) 查询语法也可以写在filter中,一般对于不需要评分的字段查询都写在filter中,可以提高查询效率。
例如:
GET product/_search
{
"query": {
"bool": {
"filter": {
"nested": {
"path": "attrs",
"query": {
"bool": {
"must": [
{
"term": {
"attrs.attrId": {
"value": "15"
}
}
}
]
}
}
}
}
}
}
}
查询结果如下: