es DSL java api

原文地址:elasticsearch DSL java api总结_简牧的博客-CSDN博客

引言
DSL,叫“特定领域语言”,是针对某一领域,具有受限表达性的一种计算机程序设计语言。elasticsearch的 query DSL即是针对elasticsearch检索的一种特定语言。
es的DSL在使用java API访问es时候也特别好用,本文我们详细了解下es的DSL java API的使用。
在使用java api检索es时候,我们使用的方式是:

            QueryBuilder builders = null;// 重点讲这个的构造
            SearchResponse response = client.prepareSearch(index)
                    .setFrom(0).setSize(100)
                    .setTimeout(TimeValue.timeValueMillis(300))
                    .setFetchSource(retFields, null)
                    .setQuery(builders)
                    .setTypes(type)
                    .execute().actionGet();

上面查询API中的setQuery就是指定查询的DSL,也是本文主要讲的。
es版本:5.1.x

query和filter
我们知道,es的查询分为两种query和filter,两种不同的上下文环境用于不同的目的。

query
使用上下文
query字句解决的问题是“文档和查询字句匹配程度”,并通过一个score分数来具体表示匹配程度。

query子句查询生效条件
直接在search API中指定query参数(通过setQuery),比如设置如下:

SearchRequestBuilder requestBuilder = client.prepareSearch(index);
requestBuilder.setQuery(QueryBuilders.termQuery("val", "field"));  // 指定query,使用的是query上下文
System.out.println(requestBuilder.toString());                     // 打印查询语句 
SearchResponse response = requestBuilder.execute().actionGet();    // 执行query

在上例中,我们通过设置query参数,使用的就是query上下文查询。如果通过toString方法打印出来,如下:

"query" : {
    "term" : {
      "field" : {
        "value" : "val",
        "boost" : 1.0
      }
    }
  }

filter
使用上下文
filter字句解决的问题是“文档和查询字句是否匹配”,只有两种情况YES和NO,不会计算分数。filter字句常用来过滤结构型数据,比如:

是否时间字段timestamp处于2015和2016之间
是否status字段被设置为true
另外,filter查询会被es缓存到内存以提高性能。

filter字句查询生效条件
触发filter上下文有三种情况:

在bool查询中指定filter参数或者must_not参数;
在 constant_score查询中指定filter参数;
filter aggregation,即filter聚合查询;
示例
如下一段查询语句:

GET /_search
{
  "query": { (1)
    "bool": { (2)
      "must": [
        { "match": { "title":   "Search"        }}, (3)
        { "match": { "content": "Elasticsearch" }}  (4)
      ],
      "filter": [ (5)
        { "term":  { "status": "published" }}, (6)
        { "range": { "publish_date": { "gte": "2015-01-01" }}} (7)
      ]
    }
  }
}

说明如下:
(1) query参数表明是query上下文;
(2)(3)(4)bool和两个match查询字句处于query上下文,用score表示匹配度;
(5) filter参数表明是filter上下文;
(6) (7) term和range子句用于filter上下文,将会过滤掉不匹配的文档,这些查询语句不会影响match查询的匹配分数;

term级别query
全文档匹配
用于匹配所有的文档,java API使用如下:

MatchAllQueryBuilder allQueryBuilder = QueryBuilders.matchAllQuery(); // match_all匹配
SearchRequestBuilder requestBuilder = client.prepareSearch(index);
requestBuilder.setQuery(allQueryBuilder); 
SearchResponse response = requestBuilder.execute().actionGet();    // 执行query

上面用于匹配index下面所有文档。

term query
说明:term级别检索是在es的倒排索引中排序的term准确的匹配。
场景:

结构化数据的查询,比如数字,日期,enum,而不是全文本字段;
低级别查询,忽略分词处理;

API使用:

TermQueryBuilder builder = QueryBuilders.termQuery("field", "val"); // 在field字段中查询val
SearchRequestBuilder requestBuilder = client.prepareSearch(index);
requestBuilder.setQuery(builder);
SearchResponse response = requestBuilder.execute().actionGet();

terms query
说明:在指定字段中查询包含任意一个term的文档。
API使用:

TermsQueryBuilder builder = QueryBuilders.termsQuery("field", "val1", "val2"); // field中包含val1或者val2
SearchRequestBuilder requestBuilder = client.prepareSearch(index);
requestBuilder.setQuery(builder);
SearchResponse response = requestBuilder.execute().actionGet();

rank query
说明:在指定的field中是否包含固定的值(一个范围值),比如数字,日期,字符串。

API使用:

RangeQueryBuilder builder = QueryBuilders.rangeQuery("age").from(20).to(40) // 从20到40
        .includeLower(true)  // 是否包含下界,即>=20
        .includeUpper(true); // 是否包含上界,即<=40
SearchRequestBuilder requestBuilder = client.prepareSearch(index);
requestBuilder.setQuery(builder);
SearchResponse response = requestBuilder.execute().actionGet();

exist query
说明:查询指定的field是否包含任意非null的值。
API使用:

ExistsQueryBuilder builder = QueryBuilders.existsQuery("field"); // 字段field是否非null
SearchRequestBuilder requestBuilder = client.prepareSearch(index);
requestBuilder.setQuery(builder);
SearchResponse response = requestBuilder.execute().actionGet();

prefix query
说明:查询指定的filed是否包含指定的前缀开头的term。
API使用:

PrefixQueryBuilder builder = QueryBuilders.prefixQuery("field", "prefix"); // 字段field是否包含prefix开头的term
SearchRequestBuilder requestBuilder = client.prepareSearch(index);
requestBuilder.setQuery(builder);
SearchResponse response = requestBuilder.execute().actionGet();


wildcard query
说明:查询指定的field是否包含符合通配符匹配的term,通配符支持?和*。
API使用:

WildcardQueryBuilder builder = QueryBuilders.wildcardQuery("field", "a?pre*"); // 字段field是否匹配a?pre*
SearchRequestBuilder requestBuilder = client.prepareSearch(index);
requestBuilder.setQuery(builder);
SearchResponse response = requestBuilder.execute().actionGet();

其他query
其他还包括ids query,type query,regexp query,类似上面一样。

全文query
即full text query,一般用户类似邮件内容、文章内容这样的全文检索,每个field对应一个analyzer,即将field内容分词并构建倒排索引。通常也会在执行检索前对query字符串进行分词(每个field对应一个analyzer或search_analyzer。

全文query相关API使用参考官网。

DSL的组合
bool query
我们经常遇到如果我的查询条件是(A || B ) && (C || D)这样情况时,该如何组织我们的API,这其实就是一个bool组合查询。
bool查询是将多种查询组合在一起,并且每个都对应一个“事件”(即must,should,must_not和filter),四种事件说明如下:

事件    描述
must    查询子句must出现在文档中,并且会影响文档得分score
filter    查询子句must出现在文档中,但是不会影响文档得分,并且会缓存
should    查询子句should出现在文档中,即并列的should子句必须有一个或者多个出现在文档中,可以通过设置参数 minimum_should_match来指定最少匹配的查询子句
must_not    查询子句一定不能出现在文档中,处于filter上下文,不影响文档得分,会被缓存
因此,bool组合查询条件就像构建一棵树一样,按照我们的逻辑构造bool查询即可,比如上述的(A || B ) && (C || D)组合构造结构如下图:

使用java api编写代码如下:

BoolQueryBuilder builder = QueryBuilders.boolQuery();
BoolQueryBuilder shoud1 = QueryBuilders.boolQuery();
TermQueryBuilder tqbA = QueryBuilders.termQuery("fieldA", "A");
TermQueryBuilder tqbB = QueryBuilders.termQuery("fieldB", "B");
shoud1.should(tqbA);
shoud1.should(tqbB);
BoolQueryBuilder shoud2 = QueryBuilders.boolQuery();
TermQueryBuilder tqbC = QueryBuilders.termQuery("fieldC", "C");
TermQueryBuilder tqbD = QueryBuilders.termQuery("fieldD", "D");
shoud2.should(tqbC);
shoud2.should(tqbD);
builder.must(shoud1);
builder.must(shoud2);
SearchRequestBuilder requestBuilder = client.prepareSearch(index);
requestBuilder.setQuery(builder);
SearchResponse response = requestBuilder.execute().actionGet();


boosting query
在实际使用过程中,我们经常用到的是,对于不同关键词的查询,我们希望不同term词对查询结果得分score的影响不同,即不同查询词的权重不同;还有一种情况就是,我们希望包含某些查询词的文档降权(而不是直接过滤掉),这时候就可以用到我们的booting查询了。
指定boost值得java示例如下:

BoolQueryBuilder builder = QueryBuilders.boolQuery();
TermQueryBuilder tqbA = QueryBuilders.termQuery("fieldA", "A").boost(5.0f);
TermQueryBuilder tqbB = QueryBuilders.termQuery("fieldB", "B").boost(2.0f);
TermQueryBuilder tqbC = QueryBuilders.termQuery("fieldC", "C").boost(0.2f);
SearchRequestBuilder requestBuilder = client.prepareSearch(index);
requestBuilder.setQuery(builder);
SearchResponse response = requestBuilder.execute().actionGet();

同样,也可以直接使用boost query,示例如下:

TermQueryBuilder tqbA = QueryBuilders.termQuery("fieldA", "A");
TermQueryBuilder tqbB = QueryBuilders.termQuery("fieldB", "B");
BoostingQueryBuilder builder = QueryBuilders.boostingQuery(tqbA, tqbB).negativeBoost(0.2f); // tqbA提权,tqbB降权
SearchRequestBuilder requestBuilder = client.prepareSearch(index);
requestBuilder.setQuery(builder);
SearchResponse response = requestBuilder.execute().actionGet();

其他组合
除了常用的bool query和boost query,还有其他几种compound query方式。比如function score query,可以指定计算文档分数的函数;constant score query,指定每个文档的分数相同;dis max query,用于指定不同的子查询分数不同,从而文档取子查询中分数最高的一个。 这些可以从官网来去学习了解
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值