当前位置:   article > 正文

Elasticsearch笔记-过滤查询_elasticsearch filter使用

elasticsearch filter使用

承接上篇文章Elasticsearch笔记-深入查询,本篇文章主要介绍过滤查询

其实准确来说,ES中的查询操作分为2种:查询(query)和过滤(filter)。查询即是之前提到的query查询,它(查询)默认会计算每个返回文档的得分,然后根据得分排序。而过滤(filter)只会筛选出符合的文档,并不计算得分,且它可以缓存文档。所以,单从性能考虑,过滤比查询更快。

换句话说,过滤适合在大范围筛选数据,而查询则适合精确匹配数据。一般应用时,应先使用过滤操作过滤数据,然后使用查询匹配数据。

过滤器使用

查询10月之前contents字段包含“ES”的文档

{
    "query": {
        "filtered":{
            "query":{
                "range":{
                    "date":{ "lte":"2016-10-01" } }
            },
            "filter":{
                "match":{
                    "contents":"ES" }
            }
        }   
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

过滤查询包含filtered关键字,里面又包含普通的查询query逻辑和filter 过滤逻辑。运行时先执行过滤语句,后执行普通查询。对比下面只使用了查询的DSL:

{
    "query": {
        "bool":{
            "must":[{
                "range":{
                    "date":{ "lte":"2016-10-01" } }
            },{
                "match":{
                    "contents":"ES" }
            }]
        }       
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

两者返回结果是一样的。

过滤器类型

过滤器类型与查询类型基本相对应,都有范围(过滤)查询、termterms等类型。

term、terms过滤

term、terms的含义与查询时一致。term用于精确匹配、terms用于多词条匹配。不过既然过滤器既然适用于大氛围过滤,term、terms在过滤中使用意义不大。

举例见前面过滤器使用一节

范围过滤(range)

查询16年10月以来所有内容含有“java”的文档,先过滤剩下符合10月的文章,再精确匹配。

{
    "query": {
        "filtered":{
            "query":{
                "match":{
                    "contents":"java" }
            },
            "filter":{
                "range":{
                    "date":{ "gte":"2016-10-01" } }
            }
        }   
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

exists、mising过滤器

exists过滤指定字段没有值的文档

{
    "query": {
        "filtered":{
            "filter":{
                "exists":{
                    "field":"id" }
            }
        }   
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

将不返回id字段无值的文档。

missing 过滤器与exists相反,它过滤指定字段有值的文档。

{
    "query": {
        "filtered":{
            "filter":{
                "missing":{
                    "field":"id" }
            }
        }   
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

只返回缺少id值的文档,与上次exists过滤结果形成互补。

标识符(ids)过滤器

需要过滤出若干指定_id的文档,可使用标识符过滤器(ids)

{
    "query": {
        "filtered":{
            "filter":{
                "ids":{
                    "values":[1,2,6,7] }
            }
        }   
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

需注意的是:指定的标识符是文档的_id,为文档唯一标识。不同于自己指定的id字段。

限定过滤器(limit)

限定过滤器限定单个分片返回的文档数。

还记得 ElasticSearch笔记-基础知识文章最后提到的分页吗?如果你查询10条数据,则每个分片都会返回10条数据,集合后再选出前10条数据。如果使用limit限定过滤器,则可限定每个分片返回文档数。

限定每个分片返回一条数据

{
    "query": {
        "filtered":{
            "filter":{
                "limit":{
                    "value":1 }
            }
        }   
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

组合过滤器

可以对这些过滤器组合使用,ES中有2类组合过滤器。一类是bool过滤器,一类是andornot过滤器。bool过滤器对应布尔查询(bool),关于两者的区别,详细解释在这里:

关于elasticsearch filter bitset的全部

这里简要说一下:

  1. bool过滤器使用了bitset结构标识该文档是否匹配,当重复执行同一过滤时可简单查询bitset结构从而提高效率。应尽量使用bool过滤。
  2. 位置过滤(Geo filter)、数值范围过滤(Numeric_range filter)、脚本过滤(Script filter)没有bitset结构,使用and、or、not过滤器更高效。

总结来说,一般情况下用bool过滤器,当遇到位置查询、数值范围、脚本查询时使用and、or、not过滤。

查询日期在16年10月份且文章标题或内容包含“ES“的文档

用SQL表示为

select * from article where date between  '2016-10-01' and  '2016-10-31' and (name like '%ES%' or contents like '%ES%')
  • 1

使用bool过滤器

{
    "query": {
        "filtered":{
            "filter":{
                "bool":{
                    "should":[{ "match":{ "name":"ES" } },{ "match":{ "contents":"ES" } }],
                    "must":{ "range":{ "date":{ "gte":"2016-10-01", "lte":"2016-10-31" } } } }
            }
        }   
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

布尔查询也可嵌套布尔查询,如要查询16年10月份内容有关ES的文章或任何时段文章名称与java相关的所有文章。(这里只是举例,不考虑实际情况)
用SQL表示为

select * from article where contents like '%ES%' and date between '2016-10-01' and '2016-10-31' or name like '%java%'
  • 1
  • 2
{
    "query": {
        "filtered": {
            "filter": {
                "bool": {
                    "should": [{ "bool": { "must": [{ "range": { "date": { "gte": "2016-09-01", "lte": "2016-09-30" } } }, { "match": { "contents": "js" } }] } }, { "match": { "name": "java" } }] }
            }
        }
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

这里解释一下,我们查询的主要用or关系连接,所以使用bool查询的should语句。一边是contents like '%ES%' and date between '2016-10-01' and '2016-10-31' ,另一个为name like '%java%' 前者需嵌套一个bool查询,使用must连接,后者简单使用match即可。

注意这种结构的写法。类似可参考Elasticsearch权威指南-组合过滤

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/807258
推荐阅读
相关标签
  

闽ICP备14008679号