ES查询方法及应用整理

ES查询1

###1.term(过滤器)查询

  • term主要用于精确匹配数字,日期,布尔值或 not_analyzed 的字符串(未经分析的文本数据类型)
  • term 查询数字(numbers)
SearchResponse response = client.prepareSearch("my_store")
                .setTypes("products")
                .setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
                .setQuery(QueryBuilders.constantScoreQuery(
                QueryBuilders.boolQuery().filter(QueryBuilders.termQuery("price", "20")))) // filter
                .setExplain(true)
                .execute()
                .actionGet();
         
        for (SearchHit searchHit : response.getHits()) {
            System.out.println(searchHit.getScore());
            Map source = searchHit.getSource();
            System.out.println(source.toString());
        }
  • term 查询文本(text)
    - query DSL中会把文本(字符串eg.XHDK-A-1293-#fJ3)拆分成几token,无法获取结果。我们需要告诉 Elasticsearch 该字段具有精确值,要将其设置成 not_analyzed 无需分析的
    - 步骤:删除索引并设置"index" : “not_analyzed” ,创建新索引并自定义映射(kibana操作语句),重新查询
    ###2.bool过滤器
  • 查询上下文中,查询操作不仅仅会进行查询,还会计算分值,用于确定相关度;在过滤器上下文中,查询操作仅判断是否满足查询条件,查询的结果可以被缓存。
  • 组成部分:(每个部分都是可选的)
    • must:所有的语句都 必须(must) 匹配,与 AND 等价。
    • must_not:所有的语句都 不能(must not) 匹配,与 NOT 等价。
    • should:至少有一个语句要匹配,与 OR 等价。
  • 简单嵌套查询
SearchRequestBuilder srq =  client.prepareSearch("forum").setTypes("article");  
        srq.setSearchType(SearchType.DFS_QUERY_AND_FETCH);  
        QueryBuilder queryBuilder=QueryBuilders.constantScoreQuery(
                 QueryBuilders.boolQuery().should(QueryBuilders.termQuery("postDate", "2017-01-01"))
                         .should(QueryBuilders.termQuery("articleID", "XHDK-A-1293-#fJ3"))
                        .mustNot(QueryBuilders.termQuery("postDate", "2017-01-02")));
         
        srq.setQuery(queryBuilder);
        SearchResponse response=srq.execute().get();
        System.out.println(srq.toString());
        for (SearchHit searchHit : response.getHits()) {
            System.out.println(searchHit.getScore());
            Map source = searchHit.getSource();
            System.out.println(source.toString());
        }
  • 复杂嵌套查询
SearchRequestBuilder srq =  client.prepareSearch("forum").setTypes("article");  
        srq.setSearchType(SearchType.DFS_QUERY_AND_FETCH);  
        srq.setQuery( QueryBuilders.boolQuery().should(
                 QueryBuilders.termQuery("productID", "XHDK-A-1293-#fJ3"))
                 .should(
                QueryBuilders.boolQuery().must(QueryBuilders.termQuery("articleID", "JODL-X-1937-#pV7"))
                 .must(QueryBuilders.termQuery("postDate", "2017-01-01"))
                         ));
        SearchResponse response=srq.execute().get();
        System.out.println(srq.toString());
        for (SearchHit searchHit : response.getHits()) {
            System.out.println(searchHit.getScore());
            Map source = searchHit.getSource();

###3.terms 多个精确值查询

  • kibane操作语言中 查询字段为数组形式
  • 构造constant_score 查询,来确保结果中的文档所包含的词项数量与要求是一致的(精确)
QueryBuilders.termsQuery("price", new int[]{10,20})

###4.范围查询

  • range 查询可同时提供包含(inclusive)和不包含(exclusive),范围表达式,可供组合的选项为:
  • gt: > 大于(greater than)
  • lt: < 小于(less than)
  • gte: >= 大于或等于(greater than or equal to)
  • lte: <= 小于或等于(less than or equal to)
  • 日期查询
//取到当天凌晨时间
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY,0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.add(Calendar.DATE,0);
        //查询今天的的数据,查询createDate 字段,大于当天0点的时间
        srb.setQuery(QueryBuilders.rangeQuery("createDate").gt(cal.getTime()));
//查询大于一个给定的时间 QueryBuilders.rangeQuery("date").format("yyyyMMdd").gt(date);
//查询区间时间  QueryBuilders.rangeQuery("date").format("yyyyMMdd").lt(beginDate).gt(endDate);
//查询小于给定时间的数据 QueryBuilders.rangeQuery("date").format("yyyyMMdd").lt(beginDate);
  • 字符串查询
    • 字典顺序或字母顺序,可直接拼接查询
    • RangeFilter实现时间范围过滤,eg.搜索文章范围在近一年之内
long current=System.currentTimeMillis()/1000l;
Calendar ca = Calendar.getInstance();//得到一个Calendar的实例  
ca.setTime(new Date());   //设置时间为当前时间  
ca.add(Calendar.YEAR, -1); //年份减1  
Date lastYear = ca.getTime(); 
QueryStringQueryBuilder queryBuilder = new QueryStringQueryBuilder("中国经济");
queryBuilder.analyzer("ik").field("title");  
FilteredQueryBuilder query = QueryBuilders.filteredQuery(queryBuilder, 
FilterBuilders.boolFilter().must(FilterBuilders.rangeFilter("updatetime").from(otherDate).to(new Date())));

###5.exists、mising过滤器

  • exists查询会返回那些 在指定字段有指定值 的文档
QueryBuilders.existsQuery("tags")
  • missing查询会返回那些 在指定字段没有值 的文档
  • 为null 或 没有值 设置 null_value 空值,不可为date类型设置且与普通值不同
    ###6.Query DSL
  • match_all 查询,可以查询到所有文档,是没有查询条件下的默认语句。
  • match 查询是一个标准查询,就指定某个确切字段某个确切的值进行搜索,全文本查询或精确查询都要用,需指定正确的字段名以避免语法错误。
  • multi_match 查询允许你做match查询的基础上同时搜索多个字段,在多个字段中同时查一个。
  • wildcards 查询,使用标准的shell通配符查询
  • regexp 查询询能够让你写下更复杂的模式,字段值可查询正则表达式
  • prefix 查询,以什么字符开头的,前缀越短,要处理的doc越多,性能越差,尽可能用长前缀搜索
QueryBuilders.prefixQuery("postcode", "W1");//以邮编为例
  • 短语匹配(Phrase Matching),需要寻找邻近的几个单词时使用
    ###7.fuzzy模糊查询
  • 自动将拼写错误的搜索文本,进行纠正,纠正以后去尝试匹配索引中的数据,对用户拼写错的场景比较有用
//普通查询
QueryBuilders.fuzzyQuery("text", "surprize");
//指定偏度差,默认偏度差2
QueryBuilders.fuzzyQuery("text", "surprize").fuzziness(Fuzziness.fromEdits(2));

###8.全文搜索

  • 相关(relevance)是将查询到相关的文档结果进行排名的一种能力,这种相关度可以是根据TF/IDF、地理位置相似性(geolocation)、模糊相似,或者其他的一些算法得出。
  • 分析(analysis) 将一个文本块转换为唯一的、规范化的token的过程,目的是为了 创建反向索引以及 查询反向索引。
  • 基于术语的查询(Term-based queries)
  • 一个 term 查询 一个术语(Foo)在反向索引中查找准确的术语,并且用 TF/IDF 算法为每个匹配的文档计算相关度 _score
  • 需要记住 term 查询只对反向索引的术语进行精确匹配,它不会对多样性进行处理(即,同时匹配foo 或 FOO)。这里,无须考虑术语是如何进入索引的
  • 基于全文的查询(Full-text queries)
  • 例: match 或 query_string 这样的高层次查询,它知道一个字段的映射
  • 查询 时间(date) 或 整数(integer),他们会将查询字符串用分别当作 时间 和 整数。
  • 查询一个准确的(未分析过的 not_analyzed)字符串字段,它会将整个查询字符串当成一个术语。
  • 查询一个全文字段(分析过的analyzed),它会讲查询字符串传入到一个合适的分析器,然后生成一个供查询的术语列表。
  • 一旦查询组成了一个术语列表,它会对每个术语逐一执行低层次的查询,然后将结果合并,为每个文档生成一个最终的相关性分数。
GET /_search
{
    "query": {
        "filtered": {
            "filter": {
                "term": { "gender": "female" }
            }
        }
    }
}

3).应用全文查询

  • 匹配查询(The match Query)多词查询(Multiword Queries) 需先建立索引和查询
GET /my_index/my_type/_search
{
    "query": {
        "match": {
            "title": "QUICK!"
        }
    }
}
  • 执行match查询步骤:

    • 检查字段类型:标题 title 字段是一个全文(analyzed) string 类型的字段,这意味着查询字符串本身也需要被分析(analyzed)

    • 分析查询字符串:将查询的字符串 QUICK! 传入标准的分析器中(standard analyzer),输出的结果是 quick。因为对于单个术语,match 查询处理的是低层次的术语查询。

    • 查找匹配文档:term 查询在反向索引中查找 quick 然后获取一组包含有术语的文档。

    • 为每个文档计算分数:term 查询为每个文档计算相关度分数,将术语频率(term frequency),即quick词在相关文档title中出现的频率,和反向文档频率(inverse document frequency),即quick在所有文档title中出现的频率,以及字段的长度,即字段越短相关度越高。

  • 组合查询(Combining Queries)组合过滤器,bool过滤器做二元判断

  • 控制分析(Controlling Analysis)

    • 保证文档在索引时与查询字符串在搜索时使用的是同一分析过程,才能使查询的术语与反向索引中的术语能够匹配;在索引时,一个字段值是根据配置或默认的分析器分析的
    • 如下:analyzer分析,匹配English
PUT /my_index/_mapping/my_type
{
    "my_type": {
        "properties": {
            "english_title": {
                "type":     "string",
                "analyzer": "english"
            }
        }
    }
}
  • 默认分析器(Default Analyzers)依次处理,直到到适合的处理器
    • analyzer 在字段映射中定义,否则
    • analyzer 在文档的 _analyzer 中指定,否则
    • type 使用的默认 analyzer,否则
    • 索引设置中名为 default 的 analyzer,否则
    • 节点设置中名为 default 的 analyzer,否则
    • 标准(standard)的 analyzer
  • 标准(standard)的 analyzer,在搜索时,顺序有些许不同
    • 定义在查询里的 analyzer,否则
    • 定义在字段映射里的 analyzer,否则
    • type 的默认 analyzer,否则
    • 索引设置中名为 default 的 analyzer,否则
    • 节点设置中名为 default 的 analyzer,否则
    • 标准(standard)的 analyzer
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值