Elasticsearch---(4)Elasticsearch DSL常用语法

3、 Elasticsearch DSL常用语法

数据准备

# 创建索引,设置分片副本,配置映射
PUT /demo
{
  "settings":{
    "number_of_replicas": 1, 
    "number_of_shards": 3
  },
  "mappings":{
    "user":{
      "properties":{
        "name":{"type":"text"},
        "age":{"type":"integer"},
        "sex":{"type":"text"},
        "remark":{"type":"text"},
        "create_time":{"type":"date","format":"yyyy-MM-dd||yyyy/MM/dd||yyyy-MM-dd HH:mm:ss||epoch_millis"}
      }
    }
  }
}

# 查看 mapping
GET /demo/user/_mapping

# 批量新增数据
POST /demo/user/_bulk
{"index":{"_index":"demo","_type":"user","_id":1}}
{"name":"kevin","age":24,"sex":"男","remark":"我是kevin","create_time":"2020-05-04"}
{"index":{"_index":"demo","_type":"user","_id":2}}
{"name":"cao","age":23,"sex":"男","remark":"我是cao","create_time":"2020-05-03"}
{"index":{"_index":"demo","_type":"user","_id":3}}
{"name":"mr.cao","age":22,"sex":"男","remark":"我是mr.cao","create_time":"2020-05-02"}
{"index":{"_index":"demo","_type":"user","_id":4}}
{"name":"kevin","age":21,"sex":"男","remark":"我是kevin","create_time":"2020-05-02"}
{"index":{"_index":"demo","_type":"user","_id":5}}
{"name":"coco","age":21,"sex":"女","remark":"我是coco","create_time":"2020-05-04"}
{"index":{"_index":"demo","_type":"user","_id":6}}
{"name":"co","age":20,"sex":"女","remark":"我是co","create_time":"2020-05-03"}
{"index":{"_index":"demo","_type":"user","_id":7}}
{"name":"coco","age":19,"sex":"女","remark":"我是coco","create_time":"2020-05-02"}

# 查询测试
# 查询name为kevin
GET /demo/user/_search?q=name:kevin

# 查询name为kevin且以age倒序
GET /demo/user/_search?q=name:kevin&sort=age:desc

3.1 DSL语句校验查询是否正确

# 查询前先校验语句是否正确
GET /demo/user/_validate/query?explain
{
  "query":{
    "match":{
      "name":"kevin"
    }
  }
}

3.2 DSL基本用法

模糊查询时使用match,精准查询时使用term。

term query:直接对关键词准确查找,该查询只适合keyword、numeric、date。

term:查询某个字段中含有某个关键词的文档。
terms:查询某个字段中含有多个关键词的文档。

match query:对所查找的关键词进行分词,在根据分词匹配查找。

match_all:查询所有文档。
multi_match:指定多个字段。
match_phrase:短语匹配查询。

ES检索引擎会先分析查询字符串,从分析后的文本中构建短语查询,表示必须匹配短语中所有的分词,并保证各个分词的相对位置不变。

from:从第几条数据开始查询。

size:需要查询的个数。

sort:实现排序,desc降序,asc升序。

range:实现范围查询。(参数:from,to,include_lower,include_upper,boost)

include_lower:是否包含范围的左边界,默认true。
include_upper:是否包含范围的右边界,默认true。

wildcard:允许使用通配符*和?进行查询

*:表示0或者多个字符
?:表示任意一个字符  

fuzzy:实现模糊查询

value:查询的关键字
boost:查询的权值,默认值1.0
min_similarity:设置匹配的最小相似度,默认值0.5,对于字符串,取值0-1(包括0和1),对于数值,取值可能大于1,对于日期,取值为1d,1m等,1d为1天。
prefix_length:指明区分词项的共同前缀长度,默认0.
max_expansions:查询中的词项可以扩展的数目,默认可以无限大。

filter是不计算相关性的,同时可以cache,所以filter效率高于query。

范围过滤:

gte:>=(大于等于)
gt:>(大于)
lte:<=(小于等于)
lt:<(小于)

bool过滤

must:必须满足的条件(and)
should:可以满足也可以不满足的条件(or)
must_not:不需要满足的条件(not)

3.3 term与terms查询

term query:直接对关键词准确查找,该查询只适合keyword、numeric、date。

term:查询某个字段中含有某个关键词的文档。
terms:查询某个字段中含有多个关键词的文档。

3.3.1 指定单个关键词查询

term查询

# term指定查询name为kevin的数据
GET /demo/user/_search
{
  "query":{
    "term":{"name":"kevin"}
  }
}

3.3.2 指定多个关键词查询

terms查询

# terms指定查询name为kevin与cao的数据
GET /demo/user/_search
{
  "query":{
    "terms":{
      "name":["kevin","cao"]
    }
  }
}

3.3.3 分页查询

from:从第几条数据开始查询,size:需要查询几条数据

# 分页查询
GET /demo/user/_search
{
  "query":{
    "terms":{
      "name":["kevin","coco"]
    }
  },
  "from":0,
  "size":3
}

3.3.4 查询时返回版本号

# 查询时返回版本号,默认version为false
GET /demo/user/_search
{
  "version":"true",
  "query": {
    "terms": {
      "name": ["kevin"]
    }
  }
}

3.4 match查询

match query:对所查找的关键词进行分词,在根据分词匹配查找。

match_all:查询所有文档。
multi_match:指定多个字段。
match_phrase:短语匹配查询。

3.4.1 查询全部(match_all)

match_all:查询所有文档。

# 查询所有用户
GET /demo/user/_search
{
  "query":{
    "match_all":{}
  }
}

3.4.2 指定单个字段查询

# 指定查询,name为kevin且以age倒序
GET /demo/user/_search
{
  "query":{
    "match":{
      "name":"kevin"
    }
  },
  "sort":[
    {
      "age":"desc"
    }
  ]
}

3.4.3 指定多个字段查询(multi_match)

multi_match:指定多个字段。

# 在多个字段中查询包含谁,kevin,coco的数据
GET /demo/user/_search
{
  "query":{
    "multi_match":{
      "query":"谁 kevin coco",
      "fields":["name","remark"]
    }
  }
}
# "query":"谁 kevin coco",查询的语句,fields查询的字段

3.4.4 短语完全匹配查询(match_phrase)

match_phrase:短语完全匹配查询。

ES检索引擎会先分析查询字符串,从分析后的文本中构建短语查询,表示必须匹配短语中所有的分词,并保证各个分词的相对位置不变。

# 精准匹配所有包含(完全匹配),必须包含
GET /demo/user/_search
{
  "query":{
    "match_phrase":{
      "remark":{
        "query":"我",
        "slop":1
      }
    }
  }
}
# "slop"是可调节因子,"slop":1则表示往后移一个单词也能匹配

3.4.5 前缀匹配查询

match_phrase_prefix:前缀匹配查询

# 匹配name的开头是co
GET /demo/user/_search
{
  "query":{
    "match_phrase_prefix":{
      "name":{
        "query":"co"
      }
    }
  }
}

3.4.6 分页查询

from:从第几条数据开始查询,size:需要查询几条数据

# 分页查询
GET /demo/user/_search
{
  "query":{
    "match":{
      "name":"kevin"
    }
  },
  "from":0,
  "size":2
}

3.4.7 查询返回指定字段

# 查询name为kevin的name,age,create_time字段
GET /demo/user/_search
{
  "query":{
    "match":{
        "name":"kevin"
    }
  },
  "_source":[
    "name",
    "age",
    "create_time"
  ]
}

3.4.8 控制加载的字段(选择性展示的字段)

includes:包含的字段展示
excludes:不包含的字段展示

# 包含的字段展示
GET /demo/user/_search
{
  "query":{
    "match_all":{}
  },
  "_source":{
    "includes":["name","sex"]
  }
}

# 不包含的字段展示
GET /demo/user/_search
{
  "query":{
    "match_all":{}
  },
  "_source":{
    "excludes":["age","create_time"]
  }
}

3.4.9 使用通配符*

# 展示字段名包含m的字段
GET /demo/user/_search
{
  "_source":{
    "includes":"*m*"
  },
  "query":{
    "match_all":{}
  }
}

# 展示字段名包含m的字段,并不展示name与最后为e的字段
GET /demo/user/_search
{
  "_source":{
    "includes":"*m*",
    "excludes":["name","*e"]
  },
  "query":{
    "match_all":{}
  }
}

3.4.10 排序

sort:实现排序,desc降序,asc升序。

# 根据age做升序排序
GET /demo/user/_search
{
  "query":{
    "match_all":{}
  },
  "sort":{
    "age":{
      "order":"asc"
    }
  }
}

3.4.11 查询范围性数据

range:实现范围查询。(参数:from,to,include_lower,include_upper,boost)

include_lower:是否包含范围的左边界,默认true。
include_upper:是否包含范围的右边界,默认true。
# 查询create_time为2020-05-01到05的数据
GET /demo/user/_search
{
  "query":{
    "range":{
      "create_time":{
        "from":"2020-05-01",
        "to":"2020-05-05"
      }
    }
  }
}

# 查询age为19到21的数据,不包含21
GET /demo/user/_search
{
  "query":{
    "range":{
      "age":{
        "from":19,
        "to":21,
        "include_lower":true,
        "include_upper":false
      }
    }
  }
}

3.4.12 wildcard模糊查询

wildcard:允许使用通配符*和?进行查询

*:表示0或者多个字符
?:表示任意一个字符  
# 模糊匹配name中最右面为co的数据
GET /demo/user/_search
{
  "query":{
    "wildcard":{
      "name":"*co"
    }
  }
}

# 模糊匹配name中c与o之间还有一个值的数据
GET /demo/user/_search
{
  "query":{
    "wildcard":{
      "name":"c?o"
    }
  }
}

3.4.13 fuzzy实现模糊查询

fuzzy:实现模糊查询

value:查询的关键字
boost:查询的权值,默认值1.0
min_similarity:设置匹配的最小相似度,默认值0.5,对于字符串,取值0-1(包括0和1),对于数值,取值可能大于1,对于日期,取值为1d,1m等,1d为1天。
prefix_length:指明区分词项的共同前缀长度,默认0.
max_expansions:查询中的词项可以扩展的数目,默认可以无限大。
# 模糊匹配分词后remark有kevin的数据
GET /demo/user/_search
{
  "query":{
    "fuzzy":{
      "remark":{
        "value":"kevin"
      }
    }
  }
}
# 比如remark的数据为我是keivn,会分词为dos[0]:我[0] 是[1] kevin[2]

3.4.13 高亮搜索结果

# 高亮显示搜索结果
GET /demo/user/_search
{
  "query":{
    "match":{
      "name":"coco"
    }
  },
  "highlight":{
    "fields": {
      "name":{}
    }
  }
}

3.5 Filter查询

filter是不计算相关性的,同时可以cache,所以filter效率高于query。

搜索结果

  • filter:只查询出搜索条件的数据,不计算相关度分数
  • query:查询出搜索条件的数据,并计算相关度分数,按照分数进行倒序排序

性能

  • filter:不计算相关度分数,也不需要排序,内置的自动缓存最常使用查询结果的数据(缓存bitset不是缓存文档内容)
  • query:要计算相关度分数,按照分数进行倒序排序,没有缓存结果的功能

当query与filter同时使用时filter会先执行,并且同时兼顾两者的特性

3.5.1 简单的过滤查询

# 过滤只取指定的结果
GET /demo/user/_search
{
  "post_filter":{
    "term":{
      "age":21
    }
  }
}

# 过滤只取指定的多个结果
GET /demo/user/_search
{
  "post_filter":{
    "terms":{
      "age":[21,23]
    }
  }
}

新增一个用户id字段设置映射不分词

PUT /demo/_mapping/user
{
  "properties":{
    "user_id":{
      "type":"text",
      "index":"false"
    }
  }
}

3.5.2 bool过滤查询

bool过滤

must:必须满足的条件(and)
should:可以满足也可以不满足的条件(or)
must_not:不需要满足的条件(not)

格式

    {
        "bool":{
            "must":[],
            "should":[],
            "must_not":[]
        }
    }

普通bool案例

#获取name=keivn or age = 20 且 age <> 24
GET /demo/user/_search
{
  "post_filter":{
    "bool":{
      "should":[
          {"term":{"name":"kevin"}},
          {"term":{"age":20}}
        ],
      "must_not":{
        "term":{"age":24}
      }
    }
  }
}

嵌套bool

# 嵌套bool,name=kevin or (name=coco and age=21)
GET /demo/user/_search
{
  "post_filter":{
    "bool":{
      "should":[
        {"term":{"name":"kevin"}},
        {
          "bool":{
            "must":[
              {"term":{"name":"coco"}},
              {"term":{"age":21}}
              ]
          }
        }
        ]
    }
  }
}

3.5.3 范围过滤

范围过滤:

gte:>=(大于等于)
gt:>(大于)
lte:<=(小于等于)
lt:<(小于)
# 范围过滤,取age>20 and age<23的数据
GET /demo/user/_search
{
  "post_filter":{
    "range":{
      "age":{
        "gt":20,
        "lt":23
      }
    }
  }
}

3.5.4 过滤非空

# 过滤非空,取name is not null 的数据
GET /demo/user/_search
{
  "query":{
    "bool":{
      "filter":{
        "exists":{
          "field":"name"
        }
      }
    }
  }
}

检索词频率TF(Term Frequency)对搜索结果排序的影响。
检索词频率:检索词在该字段出现的频率越高相关性也越高,字段中出现过多次要比一次相关性高。

constant_score:将query与filter包装,消除TF对搜索结果排序的影响。

GET /demo/user/_search
{
  "query":{
    "constant_score":{
      "filter":{
        "exists":{
          "field":"name"
        }
      }
    }
  }
}

3.5.5 过滤器缓存

ElasticSearch提供了一种特殊的缓存,即过滤器缓存(filter cache),用来存储过滤器的结果,被缓存的过滤器并不需要过多的内存(因为它们只存储了哪些文档能与过滤器相匹配的相关信息),
而且可以供后续所有与之相关的查询重复使用,从而极大的提高了查询的性能。

ElasticSearch默认缓存的过滤器:
exists,missing,range,term,terms。

ElasticSearch默认不缓存的过滤器:
numeric_range,script,geo_bbox,geo_distance,geo_distance_range
geo_polygon,geo_shape,and,or,not

开启方式:在filter查询语句后加上"_catch":true

3.6 聚合查询

sum:求总数值,等同sum()

# 聚合name=kevin的age,等同:name=kevin,sum(age)
GET /demo/user/_search
{
  "size":0,
  "aggs":{
    "age_of_sum":{
      "sum":{
        "field":"age"
      }
    }
  },
  "query":{
    "term":{
      "name":"kevin"
    }
  }
}
# "size":0,不展示原始数据,数值设为多少展示几条,不设置默认全部展示

min:求最小值,等同min()

#聚合查询,获取最小的年龄,等同min(age)
GET /demo/user/_search
{
  "size":0,
  "aggs":{
    "age_of_min":{
      "min":{
        "field":"age"
      }
    }
  }
}

max:求最大值,等同max()

#聚合查询,获取最大的年龄,等同max(age)
GET /demo/user/_search
{
  "size":0,
  "aggs":{
    "age_of_max":{
      "max":{
        "field":"age"
      }
    }
  }
}

avg:求平均值,等同avg()

#聚合查询,获取平均的年龄值,等同avg(age)
GET /demo/user/_search
{
  "size":0,
  "aggs":{
    "age_of_avg":{
      "avg":{
        "field":"age"
      }
    }
  }
}

cardinality:求基数,等同count()

# 求基数,求age有多少个数据,等同count(age)
GET /demo/user/_search
{
  "size":0,
  "aggs":{
    "age_of_cardinality":{
      "cardinality":{
        "field":"age"
      }
    }
  }
}

terms:分组,等同group by

# 分组,根据age进行分组,等同group by age
GET /demo/user/_search
{
  "size":0,
  "aggs":{
    "age_group_by":{
     "terms":{
       "field":"age"
     } 
    }
  }
}

嵌套聚合查询案例

# 嵌套聚合,获取name=kevin,根据age做分组,再根据已平均的年龄做排序,等同:name=kevin,group by age,order by avg(age)
GET /demo/user/_search
{
  "query":{
    "match":{
      "name":"kevin"
    }
  },
  "size":0,
  "aggs":{
    "age_group_by":{
      "terms":{
        "field":"age",
        "order":{
          "avg_of_age":"desc"
        }
      },
      "aggs":{
        "avg_of_age":{
          "avg":{
            "field":"age"
          }
        }
      }
    }
  }
}

3.7 复合查询

将多个基本查询组合成单一查询的查询

3.7.1 使用bool查询

参数:

must:文档必须匹配这些条件才能被包含进来。
must_not:文档必须不匹配这些条件才能被包含进来。
should:如果满足这些语句的任意语句,将增加_score,否则无任何影响,主要用于修正每个文档的相关性得分。
filter:必须匹配,但它以不评分、过滤模式来进行,这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。

相关性得分是如何组合的,每一个子查询都独自地计算文档的相关性得分,一旦得分被计算出来,bool查询就将这些得分进行合并并返回一个代表整个布尔操作的得分。

案例:

# 标识查找remark包含我是kevin的词,并且age<>21,
# should,sex=男或create_time>=2020-05-03的可以被匹配也可以不被匹配,如果匹配排名更高
GET /demo/user/_search
{
  "query":{
    "bool":{
      "must":{"match":{"remark":"我 是 kevin"}},
      "must_not":{"match":{"age":21}},
      "should":[
        {"match":{"sex":"男"}},
        {"range":{"create_time":{"gte":"2020-05-03"}}}
      ]
    }    
  }
}

改写案例:不让创建时间影响得分

# 标识查找remark包含我是kevin的词,并且age<>21,
# should,sex=男可以被匹配也可以不被匹配,如果匹配排名更高
# 避免create_time影响得分,将其过滤
GET /demo/user/_search
{
  "query":{
    "bool":{
      "must":{"match":{"remark":"我 是 kevin"}},
      "must_not":{"match":{"age":21}},
      "should":[
        {"match":{"sex":"男"}}
      ],
      "filter":{
        "range":{"create_time":{"gte":"2020-05-03"}}
      }
    }    
  }
}

通过将range查询移到filter,转成不评分的查询,将不再影响文档相关排名。
由于上一个案例是不评分的查询,可以使用各种对filter查询有效的优化来提升性能。

bool查询本身也可以被用做不评分的查询,简单地将它放置到filter语句中并在内部构建布尔逻辑。

# 标识查找remark包含我是kevin的词,并且age<>21,
# should,sex=男可以被匹配也可以不被匹配,如果匹配排名更高
# 过滤为false的,create_time>=2020-05-03,且age<=25,并name<>'coco'
GET /demo/user/_search
{
  "query":{
    "bool":{
      "must":{"match":{"remark":"我 是 kevin"}},
      "must_not":{"match":{"age":21}},
      "should":[
        {"match":{"sex":"男"}}
      ],
      "filter":{
        "bool":{
          "must":[
            {"range":{"create_time":{"gte":"2020-05-03"}}},
            {"range":{"age":{"lte":25}}}
          ],
          "must_not":[
            {"term":{"name":"coco"}}  
          ]
        }
      }
    }    
  }
}

3.7.2 constant_score查询

constant_score:将一个不变的常量评分应用于所有匹配的文档。

使用场景:常用于只需要执行一个filter而没有其它查询(例如评分查询)的情况。

term查询被放置在constant_score中,转成不评分的filter,这种方式可以用来取代只有filter语句的bool查询。

GET /demo/user/_search
{
  "constant_score":{
    "filter":{
      "term":{
        "name":"coco"
      }
    }
  }
}

你可能感兴趣的:(大数据,ELK)