DSL 被广泛使用于 Elasticsearch 的搜索中。query_string 是其中的比较特别的一种。它使用一套称之为 “mini-language” 的句法。它也被使用于 URI Search 之中。query_string 使用具有严格语法的解析器,根据提供的查询字符串返回文档。
该查询使用语法基于 OR,AND 或 NOT 等运算符来解析和拆分提供的查询字符串。 然后查询在返回匹配文档之前独立分析每个拆分文本。
你可以使用 query_string 查询创建一个复杂的搜索,其中包括通配符,跨多个字段的搜索等等。 尽管用途广泛,但查询是严格的,如果查询字符串包含任何无效语法,则返回错误。
注意:
- 由于它会针对任何无效的语法返回错误,因此我们不建议对查询框使用 query_string 查询。
- 如果你不需要支持查询语法,请考虑使用 match 查询。 如果需要查询语法的功能,请使用不太严格的 simple_query_string 查询。
在今天的练习中,我们来简单操作一下如何使用 query_string。
准备数据
我们可以利用 Kibana 自带的数据来做演示。我们按照如下的方式来加载数据:
选择 “Add sample data”:
我们选择 “Add data”,这样我们就把我们需要的样本数据加载到 Elasticsearch 了。
使用 query_string 来查询数据
我们首先来了解一下刚才我们加载的数据的字段是什么,这样我们可以根据这个来进行我们的数据查询。我们在 Kibana 中打入如下的命令来查询 kibana_sample_data_flights 索引的所有字段:
GET kibana_sample_data_flights
我们来继续如下的查询:
GET kibana_sample_data_flights/_search
{
"query": {
"query_string": {
"default_field": "Dest",
"query": "(Mariscal Sucre International Airport)"
}
}
}
注意:在上面我们把 Mariscal Sucre International Airport 整个用括号包括起来。它的意思是不对这个字符串进行分词,而是把它当做一个整体来进行搜索。
我们可以看到有如下的
我们可以看到有 237 个文档。
但是如果我们使用如下的查询:
GET kibana_sample_data_flights/_search
{
"query": {
"query_string": {
"default_field": "Dest",
"query": "(Mariscal Sucre International Airport) OR (Sheremetyevo International Airport)"
}
}
}
我们发现有更多的文档被搜寻到:
这次共有 486 个文档被搜寻到了。我们甚至可以直接省去 default_field:
GET kibana_sample_data_flights/_search
{
"query": {
"query_string": {
"query": "(Mariscal Sucre International Airport) OR (Sheremetyevo International Airport)"
}
}
}
显示的结果是 881 个文档,也就是说它不只查询 Dest 字段,也同时查询 Origin 字段。
我们可以通过如下的方式来查询:
GET kibana_sample_data_flights/_search
{
"query": {
"query_string": {
"fields": ["Origin", "Dest"],
"query": "(Mariscal Sucre International Airport) OR (Sheremetyevo International Airport)"
}
}
}
显示的结果和上面的是一样的:
我们可以使用 AND 来查询同时满足两个条件的文档:
GET kibana_sample_data_flights/_search
{
"query": {
"query_string": {
"query": "(Dest: (Stockholm-Arlanda Airport)) AND (Origin: (Gimpo International Airport))"
}
}
}
上面的查询可以查出来从 Gimpo International Airport 机场起飞到目的地 Stockholm-Arlanda Airport 机场的所有航班:
我们可以通过NOT来取发操作。比如我们想知道所有DestCountry不是SE的所有文档:
GET kibana_sample_data_flights/_search
{
"query": {
"query_string": {
"query": "NOT DestCountry:SE"
}
}
}
我们可以把field信息移到 query 的字符串上。如下的两种查询都是一样的:
GET kibana_sample_data_flights/_search
{
"query": {
"query_string": {
"query": "DestCountry: (SE OR CN)"
}
}
}
GET kibana_sample_data_flights/_search
{
"query": {
"query_string": {
"default_field": "DestCountry",
"query": "SE OR CN"
}
}
}
我们也可以进行模糊查询:
GET kibana_sample_data_flights/_search
{
"query": {
"query_string": {
"query": "DestCountry: S?"
}
}
}
上面显示所有 DestCountry 以 S 开头的文档,并且是两个字母。这里的 ?表示为任何一个字母。
如果我们想使用通配符*,我们也可以使用如下的查询:
上面查询所有在 Dest 字段里以 Stockhom 为开头的文档。
如果我们相对数字累的字段进行搜索,我们可以定义范围,比如:
- [ 1 TO 3]:查询从 1 到 3 的所有文档,包括 1 和 3
- [1 TO 3}:查询从 1 到 3 的所有的文档,但是不包括 3
- [1 TO *]: 查询从 1 以上的所有文档
- [* TO 3]:查询 3(包括 3)一下的所有的文档
我们也可以使用想如下的语法:
- dayOfWeek: >1
- dayOfWeek:>=1
- dayOfWeek:1
- dayOfWeek:<=3
- dayOfWeek:<3
我们也可以对一下字段进行加权:
更多详细的阅读,请参阅文档 Query string query | Elasticsearch Guide [8.4] | Elastic
参考: