ElasticSearch Query DSL

ElasticSearch 查询DSL(Domain Specific Language,领域特定语言),基于6.8.15版本 语法笔记。

  • Query Context(查询上下文): 除了判断文档是否匹配外,查询子句还会计算_score元数据字段中的相关性分数。每个查询子句要表达的含义是“此文档与此查询子句匹配程度如何?”
  • Filter Context(过滤器上下文):过滤上下文主要用于过滤结构化数据,Elasticsearch 会自动缓存常用的过滤器,以提高性能。每个查询子句表达的含义是“此文档是否与此查询子句匹配?”

Compounded Queries(混合查询)

Boolean Query

通过mustshouldmust_notfilter组织查询条件,形成一种或与非逻辑查询。允许逻辑嵌套。

  • must:必须满足的条件,相当于 and
  • should:满足其中一个条件即可,相当于 or
  • must not:必须不满足条件,相当于 not ,不会参与评分
  • filter:与 must 含义相同,不参与评分

举例:

// type 是低版本的概念,后续已经被作废。6.8可以填_doc 或者 不填写
POST /users{/_doc}/_search
{
  "query": {
    "bool" : {
      //注意这里的不同
      //_name 字段给每个查询条件起一个名字
      //这样在查询记录里就会多一个 matched_queries 来指明命中了那些条件
      "must" : {
        "term" : { 
            "user.id" : {"query":"kimchy" ,"_name":"fist"}
        }
      },
      "filter": {"term" : { "tags" : "production" } },
      "must_not" : {"range" : {"age" : { "gte" : 10, "lte" : 20 }}},
      "should" : [
        { "term" : { "tags" : "env1" } },
        { "term" : { "tags" : "deployed" } }
      ],
      //表示,should中n个条件,必须满足其中n个,默认为1
      "minimum_should_match" : 1,
      // 最终得分 = 分数 * boost
      "boost" : 1.0
    }
  }
}

Boosting Query

POST /articles/_search
通过 positivenegative 两种搜索条件的匹配,来正面(positive)或负面(negative)影响 _score 的计算。

POST /articles/_search
{
  "query": {
    "boosting": {
      //必须要满足的条件
      "positive": {
        "match": {
          "title": "Java"
        }
      },
      //扣分条件,满足条件则最终分数 = positive 匹配得分 * negative_boost
      "negative": {
        "match": {
          "title": "developer"
        }
      }, 
      "negative_boost": 0.1
    }
  }
}

Constant Score Query

因为filter查询,并不会计算分数,因此这种方式可以为其查询结果给出一个固定分数。

POST /articles/_search
{
  "query": {
    "constant_score": {
      //这里必须是filter
      "filter": {
        "term": {
          "title.keyword": "Java developer"
        }
      },
      // filter 最终的得分为 1.2
      "boost": 1.2
    }
  }
}

Dis Max Query (DisjunctionMaxQuery)

通过多个查询条件匹配文档,以匹配条件中最高分数作为最终得分,其他非高分匹配的条件,需要通过tie_breaker 来影响得分。

POST /articles/_search
{
  "query": {
    "dis_max": {
      //标识非最高分匹配命中,分数需要 乘以 0.7
      "tie_breaker": 0.7,
      //用于指定 Constant Score Query 这种的固定分数,constant_query 里面指定的优先
      "boost": 1.2,
      //有多个匹配条件,假设第一匹配分数最高
      //最终得分 = 第一个匹配得分 + 第二个匹配得分 * 0.7
      "queries": [
        {"match": {"title": "Java developer"}},
        {"match": {"content": "Java"}},
        {"constant_score": {
          "filter": {
            "term": {
              "title.keyword": "Java developer"
            }
          },
          //这个比外面的boost优先级高
          "boost": 3
        }}
      ]
    }
  }
}

Function Score Query

通过一些函数来计算最终的得分情况。
final_score = boost_mode(query_score,score_mode(fun_score_1...2))

  • score_mode:multiply、sum、avg、first、max、min
  • boost_mode:multiply、replace(特殊,只使用func_score,不用query_socre)、sum、avg、max、min
  • function:weight(不指定就是它)、field_value_factor(基于指定字段)、script_score(通过函数脚本)、衰减函数 (linear、exp、guass) 和 random_score(0到1浮点随机数)

下面这个例子基于:

function: weight、field_value_factor

score_mode: sum

boost_mode: sum

POST /articles/_search
{
  "query": {
    "function_score": {
     
      "boost":2,
      //这里使用 match_all 不会打分去 boost = 2,所以 query_score = 2
      "query": {"match_all": {}},
      "functions": [
        //符合次filter匹配的 fun_score_1 = size(假设10) * weight = 20
        {
          "filter": {
            "term": {
              "title.keyword": "Java developer"
            }
          },
          "weight": 2,
          "field_value_factor": {
            "field": "size"
          }
        },
        //符次filter条件的 fun_score_2 = weight = 2
        {
          "filter": {
            "match":{
              "content":"Spring"
            }
          },
          "weight": 2
        },
        //符次filter条件的 fun_score_3 = weight = 1
        {
          "filter": {
            "match":{
              "content":"NIO"
            }
          },
          "weight": 1
        }
      ],
      //functions 中多个计分方式,他们之间是通过累加的方式
      //即 fun_score = sum(fun_score_1,fun_score_2,fun_score_3) = 23
      "score_mode": "sum",
      //最终得分 = sum(query_score,fun_score)
      "boost_mode": "sum",
      // 指定 functions 的最终打分不能超过 30 Math.min(fun_score,30)
      "max_boost": 30
    }
  }
}

// script_score 使用,替代上面的 fun_score_1 中 field_value_factor 即可
"script_score": {
  "script": {
    "params": {
      "a": 5,
      "b": 1.2
    },
    "source": "params.a / Math.pow(params.b, doc['my-int'].value)"
  }
}

Full Text Queries(全文本搜索)

match

将查询文本分词后,在指定字段上进行匹配。
莱文斯坦距离:指两个字符串之间,由一个转成另一个所需的最少编辑操作次数。

  • 将一个字符替换成另一个字符
  • 插入一个字符
  • 删除一个字符
POST /articles/_search
{
  "query": {
    "match": {
      "content": {
        //这个文本会被,下面的 analyzer 
        "query": "ja1a spr0ng",
        "analyzer": "standard",
         //表示分词成term之后,查询是通过and连接的,默认是or
        "operator": "and",
        //表示是否忽略类型转换错误
        //比如说通过 size 字段(数值类型)查询传了一个 字符串默认 false 会报错的
        "lenient": "true",
        //标识是否启用模糊查询,使用 Levenshtein Edit Distance  莱文斯坦距离做模糊匹配
        //默认是0,标识精确匹配
        //AUTO表示 0-2 必须精确 3-5 支持最小编辑为1 5 以上最小编辑为 2
        "fuzziness": "AUTO",
        //模糊查询时,term 的前 2 个必须一样,从第三个字符开始允许编辑
        "prefix_length": 2,
        //表示是否过滤掉停用次,默认是none,如果期望不过滤使用 all
        "zero_terms_query": "none",
        //定义高频词,分数表示,term 出现频率 正数表示出现次数
        //在 operator 为 and match 会被改写成 bool 查询逻辑,低频次是一个must的逻辑,高频词是should的逻辑,高频词会影响到最终的得分
        "cutoff_frequency": 2
      }
    }
  }
}

match_phrase

相比于matchmatch_phrase 外强调了term的位置,也就是要求匹配文本具有一定的语法顺序。可以用来做用户输入补全。

POST /articles/_search
{
  "query": {
    "match_phrase": {
      "content": {
        //Unity3d 和 DDL 这两个词必须存在,并且顺序先后出现
        "query": "Unity3d DDL",
        //表示 Unity3d 和 DDL 中间只能差一个词
        "slop": 1
      }
    }
  }
}

match_phrase_prefix

match_phrase 一样的,但最后一个词可以只给前缀

{
  "query": {
    "match_phrase_prefix": {
      "content": {
        "query": "Spring Fr",
        //这个参数???
        "max_expansions": 0
      }
    }
  }
}

multi_match

文档多字段匹配

POST /articles/_search
{
  "query": {
    "multi_match": {
      "query": "spring",
      //content^3^3 表示content字段匹配打分会 乘以 3
      //titl* 表示模糊匹配字段,如果匹配不到会报错
      "fields": ["content^3","titl*"]
    }
  }
}

common

common存在是为了提高,低频次的匹配精度,降低停用词的影响但不排除停用词。
在实际匹配过程中,如果停用词参与了匹配那么,那么结果会出现很多无关文档,如果省略掉则会造成失语现象,如“no happy” no被去掉后可能就变成“haapy”。这时候就可以用common

POST /articles/_search
{
  "query": {
    "common": {
      "content": {
        //实际会被解析成BooleanQuery
        "query": "no Spring Framework",
        "cutoff_frequency": 0.001,
        //再and的情况下
        //非停用词是must逻辑
        //停用词是 should 逻辑
        "low_freq_operator": "and"
      }
    }
  },
  "profile": "true"
}

Term-level queries

term

针对term进行查询,如果是 exact_value(keyword)他不会被分词,term就是文本本身,如果是 full_text 文本会被分词器分成n多个term,只要其中有任何一个term在 查询条件内就会返回。

POST /articles/_search
{
  "query": {
    "term": {
      "content": {
        //这里的值一定是分词后的term值,区分大小写
        //虽然full_text 里面可能是Spring,分词后是spring ,那就应该用spring查询
        "value": "spring",
        //最终打分结果会乘以 boost
        "boost": 0
      }
    }
  }
}

Terms Query

只要字段中包括其中一个term就会返回,也允许讲其他文档的字段值作为查询条件。

POST /articles/_search
{
  "query": {"terms": {"content": ["spring","cloud"]}}
}

GET /tweets/_search
{
    "query" : {
        "terms" : {
            "user" : {
                //使用 index=users type=_doc id=2  path=followers(字段)的值作为terms query查询
                "index" : "users",
                "type" : "_doc",
                "id" : "2",
                "path" : "followers"
            }
        }
    }
}

Terms Set Query

与terms query 一样,但是可以额外制定必须匹配数量,这个数量可以来源于文档的字段,或者通过脚本计算。


POST /users/_search
{
  "query": {
    "terms_set":{
      "followers":{
        "terms":[1,30],
        // 这个表示匹配的数量必须是字段num的value
        # "minimum_should_match_field":"num",
        // 这里指明匹配的数量必须是 terms 数组的长度
        "minimum_should_match_script": {
            // Math.min(params.num_terms, doc['required_matches'].value)
           "source": "params.num_terms"
        }
      }
    }
  }
}

Range Query

范围查询 gt(大于)gte(大于等于)lt(小于)lte(小于等于)

POST /users/_search
{
  "query": {
    "range": {
      "num": {
        "gte": 1,
        "lte": 20
      }
    }
  }
}

POST /users/_search
{
  "query": {
    "range": {
      "birthday": {
        //日期字段可以使用now-1d/d 表示大于当前时间减一天的数据
        //这部分函数可以查看 Date Math 相关文档
        "gt": "now-1d/d"
      }
    }
  }
}

Exists Query

查询字段不为null 或 [] 的文档,如果想表达 not exists 就必须用 bool query 包装

POST /users/_search
{
  "query": {
    "exists": {
      "field": "followers"
    }
  }
}

POST /users/_search
{
  "query": {
    "bool": {
      "must_not": [
        {"exists": {"field": "followers"}}
      ]
    }
  }
}

Prefix Query

文本不分词,进行前缀查询

GET /_search
{ "query": {
    "prefix" : { "user" : "ki" }
  }
}

Wildcard Query

term 模糊匹配,* 0个或者多个字符 ? 表示 任何一个字符

POST /users/_search
{
  "query": {
    "wildcard": {
      "username.keyword": {
        "value": "111 ? 222"
      }
    }
  }
}

Regexp Query

正则表达式匹配,运行速度取决于正则表达式 .* 都非常慢,应该尽可能使用长前缀匹配。

  • . 表示任意一个字符
    • 表示前一个字符出现1次或者多次
    • 表示前一个字符出现0次或者多次
  • ? 表示出现0次或者一次
  • {1,4} 表示出现 大于等于1次 小于等于 4次 {4}表示出现4次,{2,}表示出现2次以上
  • (ab)+ 表示(ab)一组出现 1次或者多次
  • | 表示 一个or 的逻辑 如 aa|bb aa or bb
  • [abc] 表示 abc [a-c] 表示 abc [^abc] 表示 非 abc \ 用来表示转义 可以转移 -
  • ab~cd 表示 以a 开头紧接着是b 然后跟个非c的任何字符,以f结尾
  • <1-100> 表示一个时间范围,可以匹配到80
  • & 表示前后两个正则都需要满足,aaa.+&.+bbb aaabbb match
  • @ 表示跟任何 string 都匹配
POST /users/_search
{
  "query": {
    "regexp": {
      "username.keyword": "111.*"
    }
  }
}

Fuzzy Query

最大编辑举例匹配(莱文斯坦距离)

POST /users/_search
{
  "query": {
    "fuzzy": {
      "username.keyword": {
        "value": "111 2 2",
        //表示最大可以编辑两次
        "fuzziness": 2,
        //前面6个字符必须一样
        "prefix_length": 6,
        //???
        "max_expansions": 100
      }
    }
  }
}

Type Query

index 下 类型查找,之后类型被弱化了,所以没什么用了

POST /users/_search
{
  "query": {
    "type":{
      "value":"_doc"
    }
  }
}

Ids Query

查询制定id的文档

GET /users/_search
{
    "query": {
        "ids" : {
            "type" : "_doc",
            "values" : ["1", "4", "100"]
        }
    }
}

操作的时候不制定前面的索引,直接使用/_search 将会搜索所有的索引

你可能感兴趣的:(ElasticSearch Query DSL)