当前位置: 首页>数据库>正文

es高级api插入数据 es java api

引言
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,用于指定不同的子查询分数不同,从而文档取子查询中分数最高的一个。 这些可以从官网来去学习了解
 


https://www.xamrdz.com/database/6wq1923178.html

相关文章: