ElasticSearch 查询语法


查询的基本语法结构


GET /{index}/{type}/_search
{
    "from": 0,  // 搜索结果的开始位置
    "size": 5,  // 分页大小,每页显示数量
    "_source": ["field_1", "field_2", "field_3"],  // 需要返回的字段数组
    "query": {
        "bool": {
            "must": [],  // must 条件,类似 sql 中的 and,代表必须匹配条件
            "must_not": [],  // must_not 条件,跟 must 相反,必须不匹配条件,相当于 sql 语句中的 `!=`
            "should": [],  // should 条件,类似 sql 中的 or,代表匹配其中一个条件
        }
    },  // query 子句
    "aggs": {},  // aggs 子句,主要用来编写统计分析语句,类似 sql 的 group by 子句
    "sort": [
        {
            "{field1}": {  // 需要排序的字段
                "order": "desc"  // 排序的规则,asc 升序,desc 降序
            }
        },
        {
            "{field2}": {
                "order": "asc"
            }
        }
    ]  // 排序子句
}


# 也可以多个索引同时查询
# 多个索引同时查询时,用逗号分隔,比如:
GET /{index1},{index2},{index3}/_doc/_search
# 或者使用前缀模糊匹配,比如:
GET /rcp_goods_img_*/_doc/_search

Filter 和 Query

任何一个 document 对于 filter 来说,就是 match 与否 的问题,是个二值问题,0 和 1 没有 scroing 的过程,但是使用 query 的时候,是表示 match 程度问题,有 scroing 过程

es 底层对 filter 做了很多优化,会对过滤结果进行缓存,同时,filter 没有相关性计算过程,所以 filter 比 query 快。

所以,官网推荐,作为一条比较通用的规则:仅在全文检索时,使用 Query,其它时候都用 Filter,但是还是得按照我们的实际情况来看,毕竟有些时候用空间换时间不一定划算。

match 和 term

match 查询的时候,es 会根据你给定的字段提供合适的分析器,而 term 查询不会有分析器分析的过程,match 查询相当于模糊匹配,只包含其中一部分关键词就行。match 系列匹配时,datatype 要设置为 text ,否则不会开启分词

match_all

表示取出所有 documents,在与 filter 结合使用时,会经常用到 match_all


# 查询所有数据(查询所有的索引对应的所有文档)
GET _search
{
  "query": {
    "match_all": {}
  }
}

# 查指定索引下所有的数据
GET /rcp_goods_img_*/_doc/_search
{
  "query": {
    "match_all": {}
  }
}

match

一般在全文检索时使用,首先利用 analyzer(分词器)对具体查询字符串进行分析,然后进行查询。但是在查询,比如说数值型字段、日期型字段、布尔字段或者不需要分词的字符串上进行查询时,表示精确匹配


# 示例
# select goods_id, app_name from rcp_goods_img_checks._doc where goods_id = m43337929006 order by app_name desc
GET /rcp_goods_img_checks/_doc/_search
{
  "_source": [
    "goods_id",
    "app_name"
  ],
  "query": {
    "match": {
      "goods_id": "m43337929006"
    }
  },
  "sort": [
    {
      "app_name": {
        "order": "desc"
      }
    }
  ]
}

multi_match

同时对查询的关键词进行多字段同时匹配,只要其中一个字段匹配到值就返回结果


# 示例
# 只要查询的字段 check_status 、app_name 、site_id 这三个字段中任意一个字段为 19 那么就返回结果
# select * from rcp_goods_img_checks._doc where check_status = 19 or app_name = 19 or site_id = 19
GET /rcp_goods_img_checks/_doc/_search
{
  "query": {
    "multi_match": {
      "query": 19,
      "fields": ["check_status", "app_name", "site_id"]
    }
  }
}

match_phrase_prefix

左前缀匹配,类似 sql 中的 like field%


# 示例
# select * from rcp_goods_img_checks._doc where goods_id like 'm%'
GET /rcp_goods_img_checks/_doc/_search
{
  "query": {
    "match_phrase_prefix": {
      "goods_id": "m"
    }
  }
}

term

term 用于精确查找,可用于数值、日期、布尔值或者不需要分词的字符串,当使用 term 时,不会对查询字符串进行分析,进行的是精确查找


# 示例

# 字段只有一个值时,精确查询
# select * from rcp_goods_img_checks._doc where site_id = 18
GET /rcp_goods_img_checks/_search
{
  "query": {
    "term": {
      "site_id": "18"
    }
  }
}

# 因为是精确查询,因此不需要查询进行评分计算
# 使用 constant_score 查询以非评分模式来执行 term 查询,并作为统一评分
GET /rcp_goods_img_checks/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "site_id": "18"
        }
      }
    }
  }
}

terms

terms 和 term 类似,terms 可以指定多个值,只要 doc 满足 terms 里的任意值,就是满足查询条件的,属于精确查找

terms 表示的是 contains 关系,而不是 equals 关系


# 示例

# 字段有多个值时
# select * from rcp_goods_img_checks._doc where site_id in ("18", "20")
GET /rcp_goods_img_checks/_search
{
  "query": {
    "terms": {
      "site_id": ["18", "20"]
    }
  }
}

# 使用 constant_score 查询以非评分模式来执行 terms 查询,并作为统一评分
GET /rcp_goods_img_checks/_search
{
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "site_id": ["18", "20"]
        }
      }
    }
  }
}

range

范围查找

操作符可以是:

  • gt:大于
  • gte:大于等于
  • lt:小于
  • lte:小于等于

# select * from rcp_goods_img_checks._doc where site_id >= 19 and site_id < 30
GET /rcp_goods_img_checks/_doc/_search
{
  "query": {
    "range": {
      "site_id": {
        "gte": 19,
        "lt": 30
      }
    }
  }
}

exists 和 missing

exists 用于查找某个字段含有一个或者多个值对应的 document,而 missing 用于查找某个字段不存在值对应的 document,类比关系数据库中的 is not null 等同于 existsis null 等同于 missing


# select * from rcp_goods_img_checks._doc where title is not null

{
    "exists": {
        "field": "title"
    }
}


# select * from rcp_goods_img_checks._doc where title is null

{
    "missing": {
        "field": "title"
    }
}

bool

使用 bool 子句来将各种子查询关联起来,组建布尔表达式,实现复合查询,bool 子句可以随意组合、嵌套。

bool 子句主要包括:

  • must:表示必须匹配,与 and 等价(贡献算分)
  • must_not:表示一定不能匹配,与 not 等价(不贡献算分)
  • should:表示可以匹配,类似于布尔运算里面的逻辑或 与 or 等价(贡献算分)
  • filter:过滤子句,必须匹配(不贡献算分)

如果 bool 子句里,没有 must 子句,那么,should 子句里至少匹配一个,如果有 must 子句,那么,should 子句至少匹配 0 个。可以使用 minimum_should_match 来对最小匹配数进行设置。


{
    "bool" : {
        "must" : {
            "term" : { "name" : "kimchy" }
        },
        "must_not" : {
            "range" : {
                "age" : { "from" : 10, "to" : 20 }
            }
        },
        "should" : [
            {
                "term" : { "tag" : "v1" }
            },
            {
                "term" : { "tag" : "v1.0.2" }
            }
        ],
        "minimum_should_match" : 1,
        "boost" : 1.0
    }
}

# select * from rcp_goods_img_checks._doc where app_name = 2 and site_id = 18 and updated_at between 0 and 1659695794 order by updated_at desc limit 100
GET /rcp_goods_img_checks/_doc/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "term": {
            "app_name": 2
          }
        },
        {
          "term": {
            "site_id": 18
          }
        }
      ],
      "filter": [
        {
          "range": {
            "updated_at": {
              "from": 0,
              "to": 1659695794
            }
          }
        }
      ]
    }
  },
  "size": 100,
  "sort": [
    {
      "updated_at": "desc"
    }
  ]
}

文章作者: Alex
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Alex !
评论
  目录