✅P110-118_全文检索-ElasticSearch-进阶-两种查询方式

gong_yz大约 7 分钟谷粒商城

1、SearchAPI

ES 支持两种基本方式检索 :

  • 一个是通过使用 REST request URI 发送搜索参数(uri+检索参数)
  • 另一个是通过使用 REST request body 来发送它们(uri+请求体)

1.1 检索信息

一切检索从_search 开始

GET bank/_search检索 bank 下所有信息, 包括 type 和 docs
GET bank/_search?q=*&sort=account_number:asc请求参数方式检索

响应结果解释:

  • took:Elasticsearch 执行搜索的时间( 毫秒)
  • time_out:告诉我们搜索是否超时
  • _shards:告诉我们多少个分片被搜索了, 以及统计了成功/失败的搜索分片
  • hits:搜索结果
  • hits.total:搜索结果
  • hits.hits:实际的搜索结果数组( 默认为前 10 的文档)
  • sort:结果的排序 key( 键) ( 没有则按 score 排序)
  • scoremax_score:相关性得分和最高得分( 全文检索用)

uri+请求体进行检索

测试内容

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "account_number": {
        "order": "desc"
      }
    }
  ]
}

测试结果

注意

  • HTTP 客户端工具( POSTMAN) , get 请求不能携带请求体, 我们变为 post 也是一样的。我们 POST 一个 JSON 风格的查询请求体到 _search API。
  • 需要了解, 一旦搜索的结果被返回, Elasticsearch 就完成了这次请求, 并且不会维护任何服务端的资源或者结果的 cursor( 游标)

2、Query DSL

2.1 基本语法格式

Elasticsearch 提供了一个可以执行查询的 Json 风格的 DSL( domain-specific language 领域特定语言) 。 这个被称为 Query DSL。 该查询语言非常全面,真正学好它的方法是从一些基础的示例开始的。

一个查询语句的典型结构

{
	QUERY_NAME: {
		ARGUMENT: VALUE,
		ARGUMENT: VALUE,...
	}
}

如果是针对某个字段, 那么它的结构如下

{
	QUERY_NAME: {
		FIELD_NAME: {
			ARGUMENT: VALUE,
			ARGUMENT: VALUE,...
		}
	}
}

1、query 定义如何查询, 2、match_all 查询类型【代表查询所有的所有】 , es 中可以在 query 中组合非常多的查询类型完成复杂查询 3、除了 query 参数之外, 我们也可以传递其它的参数以改变查询结果。 如 sort, size 4、from+size 限定, 完成分页功能 5、sort 排序, 多字段排序, 会在前序字段相等时后续字段内部排序, 否则以前序为准

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "from": 0,
  "size": 5, 
  "sort": [
    {
      "account_number": {
        "order": "desc"
      }
    }
  ]
}

2.2 返回部分字段

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "from": 0,
  "size": 5, 
  "_source":["firstname","age"]
}

2.3 match【 匹配查询】

match 返回 account_number=20 的

GET bank/_search
{
  "query": {
    "match": {
      "account_number": "20"
    }
  }
}

字符串, 全文检索。

最终查询出 address 中包含 mill 单词的所有记录。

match 当搜索字符串类型的时候, 会进行全文检索, 并且每条记录有相关性得分。

GET bank/_search
{
  "query": {
    "match": {
      "address": "mill"
    }
  }
}

字符串, 多个单词( 分词+全文检索)。

最终查询出 address 中包含 mill 或者 road 或者 mill road 的所有记录, 并给出相关性得分。

GET bank/_search
{
  "query":{
    "match": {
      "address": "mill road"
    }
  }
}

2.4 match_phrase【 短语匹配】

将需要匹配的值当成一个整体单词( 不分词) 进行检索。

查出 address 中包含 mill road 的所有记录, 并给出相关性得分。

注意

字段.keyword 精确value

2.5 multi_match【 多字段匹配】

state 或者 address 包含 mill

2.6 bool【 复合查询】

  • bool 用来做复合查询:
  • 复合语句可以合并任何其它查询语句,包括复合语句,了解这一点是很重要的。这就意味着, 复合语句之间可以互相嵌套,可以表达非常复杂的逻辑。

must: 必须达到 must 列举的所有条件

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "address": "mill"
          }
        },
        {
          "match": {
            "gender": "M"
          }
        }
      ]
    }
  }
}

should: 应该达到 should 列举的条件, 如果达到会增加相关文档的评分, 并不会改变查询的结果。 如果 query 中只有 should 且只有一种匹配规则, 那么 should 的条件就会被作为默认匹配条件而去改变查询结果

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "address": "mill"
          }
        },
        {
          "match": {
            "gender": "M"
          }
        }
      ],
      "should": [
        {
          "match": {
            "address": "lane"
          }
        }
      ]
    }
  }
}

must_not 必须不是指定的情况

address 包含 mill, 并且 gender 是 M, 如果 address 里面有 lane 最好不过, 但是 email 必须不包含 baluba.comopen in new window

GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "address": "mill"
          }
        },
        {
          "match": {
            "gender": "M"
          }
        }
      ],
      "should": [
        {
          "match": {
            "address": "lane"
          }
        }
      ],
      "must_not": [
        {
          "match": {
            "email": "baluba.com"
          }
        }
      ]
    }
  }
}

2.7 filter【结果过滤】

并不是所有的查询都需要产生分数, 特别是那些仅用于 “filtering”(过滤) 的文档。 为了不计算分数 Elasticsearch 会自动检查场景并且优化查询的执行。

2.8 term

和 match 一样。 匹配某个属性的值。

  • 全文检索字段用 match(address字段)
  • 其他非 text 字段匹配用 term(如age精确值)。
  • term查询是完全匹配
  • term查询不会再进行分词,而是直接去分词库进行完全匹配查询;

terms 特点:

  • 查询某个字段里含有多个关键词的文档
  • 相对于term来,terms是在针对一个字段包含多个值的时候使用
  • 通俗来说就是term查询一次可以匹配一个条件,terms一个可以匹配多个条件;
GET bank/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "age": {
              "value": "28"
            }
          }
        },
        {
          "match": {
            "address": "990 Mill Road"
          }
        }
      ]
    }
  }
}

2.9 aggregations( 执行聚合)

聚合提供了从数据中分组和提取数据的能力。 最简单的聚合方法大致等于 SQL GROUP BY 和 SQL 聚合函数。 在 Elasticsearch 中, 您有执行搜索返回 hits( 命中结果) , 并且同时返回聚合结果, 把一个响应中的所有 hits( 命中结果) 分隔开的能力。 这是非常强大且有效的,您可以执行查询和多个聚合, 并且在一次使用中得到各自的( 任何一个的) 返回结果, 使用一次简洁和简化的 API 来避免网络往返。

聚合语法如下

"aggs": {
		"aggs_name 这次聚合的名字, 方便展示在结果集中": {
			"AGG_TYPE 聚合的类型( avg,term,terms) ": {}
		}
},

搜索 address 中包含 mill 的所有人的年龄分布以及平均年龄, 但不显示这些人的详情

  • size: 0 不显示搜索数据,如果size有值或者不加size: 0,那么将看不到聚合结果
  • aggs: 执行聚合
GET bank/_search
{
  "query": {
    "match": {
      "address": "mill"
    }
  },
  "aggs": {
    "group_by_age": {
      "terms": {
        "field": "age"
       }
      },
      "avg_age":{
        "avg": {
          "field": "age"
        }
      }
  },
  "size": 0
}

按照年龄聚合, 并且请求这些年龄段的这些人的平均薪资

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "aggs_age": {
      "terms": {
        "field": "age",
        "size": 100
      },
      "aggs": {
        "aggs_balance": {
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  },
  "size": 0
}

复杂: 查出所有年龄分布, 并且这些年龄段中 M 的平均薪资和 F 的平均薪资以及这个年龄段的总体平均薪资

类似于套娃,先查出年龄分布信息,在年龄分布中聚合出性别信息,在性别中聚合M和F的平均工资,总体平均薪资和性别聚合在一个层级上! "field": "gender.keyword" gender是txt没法聚合 必须加.keyword精确替代

GET bank/_search
{
  "query": {
    "match_all": {}
  },
  "aggs": {
    "age_Aggs": {
      "terms": {
        "field": "age",
        "size": 100
      },
      "aggs": {
        "sex_Aggs": {
          "terms": {
            "field": "gender.keyword"
          },
          "aggs": {
            "balance_Avg_Aggs": {
              "avg": {
                "field": "balance"
              }
            }
          }
        },
        "total_avg_balance_Aggs":{
          "avg": {
            "field": "balance"
          }
        }
      }
    }
  },
  "size": 0
}