[ElasticSearch]Java API 之 词条查询(Term Level Query)

原创 2016年10月18日 20:52:33

1. 词条查询(Term Query) 

词条查询是ElasticSearch的一个简单查询。它仅匹配在给定字段中有该词条的文档,而且是确切的、未经分析的词条。term 查询 会查找我们设定的准确值。term 查询本身很简单,它接受一个字段名和我们希望查找的值。

下面代码查询将匹配 college 字段中含有"California"一词的文档。记住,词条查询是未经分析的,因此需要提供跟索引文档中的词条完全匹配的词条。请注意,我们使用小写开头的california来搜索,而不是California,因为California一词在建立索引时已经变成了california(默认分词器)。

  1.    /**
  2.     * 词条查询
  3.     * @param client
  4.     * @param index
  5.     * @param type
  6.     */
  7.    public static void termQuery(Client client, String index, String type) {
  8.        // Query
  9.        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("country", "AWxhOn".toLowerCase());
  10.        // Search
  11.        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  12.        searchRequestBuilder.setTypes(type);
  13.        searchRequestBuilder.setQuery(termQueryBuilder);
  14.        // 执行
  15.        SearchResponse searchResponse = searchRequestBuilder.get();
  16.        // 结果
  17.        queryResult(searchResponse);
  18.    }

参考:https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-term-query.html


2. 多词条查询(Terms Query)

词条查询(Term Query)允许匹配单个未经分析的词条,多词条查询(Terms Query)可以用来匹配多个这样的词条。只要指定字段包含任一我们给定的词条,就可以查询到该文档。

下面代码得到所有在 country 字段中含有 “德国” 或 "比利时" 的文档。

  1.    /**
  2.     * 多词条查询
  3.     * @param client
  4.     * @param index
  5.     * @param type
  6.     */
  7.    public static void termsQuery(Client client, String index, String type) {
  8.        // Query
  9.        TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("country", "比利时", "德国");
  10.        // Search
  11.        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  12.        searchRequestBuilder.setTypes(type);
  13.        searchRequestBuilder.setQuery(termsQueryBuilder);
  14.        // 执行
  15.        SearchResponse searchResponse = searchRequestBuilder.get();
  16.        // 结果
  17.        queryResult(searchResponse);
  18.    }
输出结果:
  1. 20:59:52.901 [main] INFO  com.sjf.open.api.QueryAPI - ---------- QueryAPI id 9 score 0.4898842 source {country=比利时, name=阿扎尔, club=切尔西俱乐部}
  2. 20:59:52.901 [main] INFO  com.sjf.open.api.QueryAPI - ---------- QueryAPI id 4 score 0.39103588 source {country=德国, name=穆勒, club=拜仁慕尼黑俱乐部}
  3. 20:59:52.901 [main] INFO  com.sjf.open.api.QueryAPI - ---------- QueryAPI id 1 score 0.25427115 source {country=比利时, name=德布劳内, club=曼城俱乐部}

参考:https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-terms-query.html


3. 范围查询(Range Query)

范围查询使我们能够找到在某一字段值在某个范围里的文档,字段可以是数值型,也可以是基于字符串的。范围查询只能针对单个字段。

方法:

(1)gte() :范围查询将匹配字段值大于或等于此参数值的文档。

(2)gt() :范围查询将匹配字段值大于此参数值的文档。

(3)lte() :范围查询将匹配字段值小于或等于此参数值的文档。

(4)lt() :范围查询将匹配字段值小于此参数值的文档。

(5)from() 开始值  to() 结束值  这两个函数与includeLower()和includeUpper()函数配套使用。

includeLower(true) 表示 from() 查询将匹配字段值大于或等于此参数值的文档;

includeLower(false) 表示 from() 查询将匹配字段值大于此参数值的文档;

includeUpper(true) 表示 to() 查询将匹配字段值小于或等于此参数值的文档;

includeUpper(false) 表示 to() 查询将匹配字段值小于此参数值的文档;

  1.    /**
  2.     * 范围查询
  3.     * @param client
  4.     * @param index
  5.     * @param type
  6.     */
  7.    public static void rangeQuery(Client client, String index, String type) {
  8.        // Query
  9.        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age");
  10.        rangeQueryBuilder.from(19);
  11.        rangeQueryBuilder.to(21);
  12.        rangeQueryBuilder.includeLower(true);
  13.        rangeQueryBuilder.includeUpper(true);
  14.        //RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age").gte(19).lte(21);
  15.        // Search
  16.        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  17.        searchRequestBuilder.setTypes(type);
  18.        searchRequestBuilder.setQuery(rangeQueryBuilder);
  19.        // 执行
  20.        SearchResponse searchResponse = searchRequestBuilder.execute().actionGet();
  21.        // 结果
  22.        queryResult(searchResponse);
  23.    }

上面代码中的查询语句与下面的是等价的:

  1. QueryBuilder queryBuilder = QueryBuilders.rangeQuery("age").gte(19).lte(21);

输出结果:

  1. 22:29:27.206 [main] INFO  com.sjf.open.api.QueryAPI - ---------- QueryAPI id 9 score 1.0 source {college=计算机学院, school=麻省理工大学, sex=boy, name=廖力生, age=21}
  2. 22:29:27.209 [main] INFO  com.sjf.open.api.QueryAPI - ---------- QueryAPI id 2 score 1.0 source {college=通信学院, school=西安电子科技大学, sex=boy, name=李源一, age=19}
  3. 22:29:27.209 [main] INFO  com.sjf.open.api.QueryAPI - ---------- QueryAPI id 4 score 1.0 source {college=电子工程学院, school=中国科技大学, sex=girl, name=王俊辉, age=21}
  4. 22:29:27.209 [main] INFO  com.sjf.open.api.QueryAPI - ---------- QueryAPI id 1 score 1.0 source {college=计算机学院, school=西安电子科技大学, sex=boy, name=徐欣, age=21}
  5. 22:29:27.209 [main] INFO  com.sjf.open.api.QueryAPI - ---------- QueryAPI id 11 score 1.0 source {college=计算机学院ddddd, school=中国科技大学, sex=girl, name=王俊辉2, age=21}

参考:https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-range-query.html


4. 存在查询(Exists Query)

如果指定字段上至少存在一个no-null的值就会返回该文档。

  1.    /**
  2.     * 存在查询
  3.     * @param client
  4.     * @param index
  5.     * @param type
  6.     */
  7.    public static void existsQuery(Client client, String index, String type) {
  8.        // Query
  9.        ExistsQueryBuilder existsQueryBuilder = QueryBuilders.existsQuery("name");
  10.        // Search
  11.        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  12.        searchRequestBuilder.setTypes(type);
  13.        searchRequestBuilder.setQuery(existsQueryBuilder);
  14.        // 执行
  15.        SearchResponse searchResponse = searchRequestBuilder.get();
  16.        // 结果
  17.        queryResult(searchResponse);
  18.    }

举例说明,下面的几个文档都会得到上面代码的匹配:

  1. { "name": "yoona" }
  2. { "name": "" }
  3. { "name": "-" }
  4. { "name": ["yoona"] }
  5. { "name": ["yoona", null ] }

第一个是字符串,是一个非null的值。

第二个是空字符串,也是非null。

第三个使用标准分析器的情况下尽管不会返回词条,但是原始字段值是非null的(Even though the standard analyzer would emit zero tokens, the original field is non-null)。

第五个中至少有一个是非null值。

下面几个文档不会得到上面代码的匹配:

  1. { "name": null }
  2. { "name": [] }
  3. { "name": [null] }
  4. { "user":  "bar" }

第一个是null值。

第二个没有值。

第三个只有null值,至少需要一个非null值。

第四个与指定字段不匹配。

参考:https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-exists-query.html


5. 前缀查询(Prefix Query)

前缀查询让我们匹配这样的文档:它们的特定字段已给定的前缀开始。下面代码中我们查询所有country字段以"葡萄"开始的文档。

  1.    /**
  2.     * 前缀查询
  3.     * @param client
  4.     */
  5.    public static void prefixQuery(Client client, String index, String type) {
  6.        // Query
  7.        PrefixQueryBuilder prefixQueryBuilder = QueryBuilders.prefixQuery("country", "葡萄");
  8.        
  9.        // Search
  10.        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  11.        searchRequestBuilder.setTypes(type);
  12.        searchRequestBuilder.setQuery(prefixQueryBuilder);
  13.        // 执行
  14.        SearchResponse searchResponse = searchRequestBuilder.get();
  15.        // 结果
  16.        queryResult(searchResponse);
  17.    }

输出结果:

  1. 11:27:46.358 [main] INFO  com.sjf.open.api.QueryAPI - ---------- QueryAPI id 3 score 1.0 source {country=葡萄牙, name=C罗, club=皇家马德里俱乐部}

备注:

进行下面前缀查询,没有查找到相应信息,但是数据源中是有的:

  1. QueryBuilder queryBuilder = QueryBuilders.prefixQuery("club", "皇家马德里");

产生以上差别的主要原因是club字段(默认mapping配置)进行了分析器分析了,索引中的数据已经不在是"皇家马德里",而country字段没有进行分析(mapping配置not_analyzed)。

参考:https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-prefix-query.html


6. 通配符查询(Wildcard Query)

通配符查询允许我们获取指定字段满足通配符表达式的文档,和前缀查询一样,通配符查询指定字段是未分析的(not analyzed)。

可以使用星号代替0个或多个字符,使用问号代替一个字符。星号表示匹配的数量不受限制,而后者的匹配字符数则受到限制。这个技巧主要用于英文搜索中,如输入““computer*”,就可以找到“computer、computers、computerised、computerized”等单词,而输入“comp?ter”,则只能找到“computer、compater、competer”等单词。注意的是通配符查询不太注重性能,在可能时尽量避免,特别是要避免前缀通配符(以以通配符开始的词条)。

  1.    /**
  2.     * 通配符查询
  3.     * @param client
  4.     * @param index
  5.     * @param type
  6.     */
  7.    public static void wildcardQuery(Client client, String index, String type){
  8.        // Query
  9.        WildcardQueryBuilder wildcardQueryBuilder = QueryBuilders.wildcardQuery("country", "西*牙");
  10.        // Search
  11.        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  12.        searchRequestBuilder.setTypes(type);
  13.        searchRequestBuilder.setQuery(wildcardQueryBuilder);
  14.        // 执行
  15.        SearchResponse searchResponse = searchRequestBuilder.get();
  16.        // 结果
  17.        queryResult(searchResponse);
  18.    }

输出结果:

  1. 15:13:10.163 [main] INFO  c.sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 8 score 1.0 source {country=西班牙, name=托雷斯, club=马德里竞技俱乐部}
  2. 15:13:10.163 [main] INFO  c.sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 6 score 1.0 source {country=西班牙, name=布斯克茨, club=巴萨罗那俱乐部}
  3. 15:13:10.163 [main] INFO  c.sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 7 score 1.0 source {country=西班牙, name=哈维, club=巴萨罗那俱乐部}

参考:https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-wildcard-query.html


7. 正则表达式查询(Regexp Query)

正则表达式查询允许我们获取指定字段满足正则表达式的文档,和前缀查询一样,正则表达式查询指定字段是未分析的(not analyzed)。正则表达式查询的性能取决于所选的正则表达式。如果我们的正则表达式匹配许多词条,查询将很慢。一般规则是,正则表达式匹配的词条数越高,查询越慢。

  1.    /**
  2.     * 正则表达式查询
  3.     * @param client
  4.     * @param index
  5.     * @param type
  6.     */
  7.    public static void regexpQuery(Client client, String index, String type){
  8.        // Query
  9.        RegexpQueryBuilder regexpQueryBuilder = QueryBuilders.regexpQuery("country", "(西班|葡萄)牙");
  10.        
  11.        // Search
  12.        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  13.        searchRequestBuilder.setTypes(type);
  14.        searchRequestBuilder.setQuery(regexpQueryBuilder);
  15.        // 执行
  16.        SearchResponse searchResponse = searchRequestBuilder.get();
  17.        // 结果
  18.        queryResult(searchResponse);
  19.    }

输出结果:

  1. 15:36:13.833 [main] INFO  c.sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 8 score 1.0 source {country=西班牙, name=托雷斯, club=马德里竞技俱乐部}
  2. 15:36:13.833 [main] INFO  c.sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 6 score 1.0 source {country=西班牙, name=布斯克茨, club=巴萨罗那俱乐部}
  3. 15:36:13.833 [main] INFO  c.sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 7 score 1.0 source {country=西班牙, name=哈维, club=巴萨罗那俱乐部}
  4. 15:36:13.834 [main] INFO  c.sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 3 score 1.0 source {country=葡萄牙, name=C罗, club=皇家马德里俱乐部}

参考:https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-regexp-query.html


8. 模糊查询(Fuzzy Query)

如果指定的字段是string类型,模糊查询是基于编辑距离算法来匹配文档。编辑距离的计算基于我们提供的查询词条和被搜索文档。如果指定的字段是数值类型或者日期类型,模糊查询基于在字段值上进行加减操作来匹配文档(The fuzzy query uses similarity based on Levenshtein edit distance for string fields, and a +/-margin on numeric and date fields)。此查询很占用CPU资源,但当需要模糊匹配时它很有用,例如,当用户拼写错误时。另外我们可以在搜索词的尾部加上字符 “~” 来进行模糊查询。

8.1 string类型字段

模糊查询生成所有可能跟指定词条的匹配结果(在fuzziness指定的最大编辑距离范围之内)。然后检查生成的所有结果是否是在索引中。

下面代码中模糊查询country字段为”西班牙“的所有文档,同时指定最大编辑距离为1(fuzziness),最少公共前缀为0(prefixLength),即不需要公共前缀。

  1.    /**
  2.     * 模糊查询
  3.     * @param client
  4.     * @param index
  5.     * @param type
  6.     */
  7.    public static void fuzzyQuery(Client client, String index, String type){
  8.        // Query
  9.        FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("country", "洗班牙");
  10.        // 最大编辑距离
  11.        fuzzyQueryBuilder.fuzziness(Fuzziness.ONE);
  12.        // 公共前缀
  13.        fuzzyQueryBuilder.prefixLength(0);
  14.        // Search
  15.        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  16.        searchRequestBuilder.setTypes(type);
  17.        searchRequestBuilder.setQuery(fuzzyQueryBuilder);
  18.        // 执行
  19.        SearchResponse searchResponse = searchRequestBuilder.get();
  20.        // 结果
  21.        queryResult(searchResponse);
  22.    }

输出结果:

  1. 20:01:48.160 [main] INFO  c.sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 8 score 1.6931472 source {country=西班牙, name=托雷斯, club=马德里竞技俱乐部}
  2. 20:01:48.161 [main] INFO  c.sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 6 score 1.4054651 source {country=西班牙, name=布斯克茨, club=巴萨罗那俱乐部}
  3. 20:01:48.161 [main] INFO  c.sjf.open.api.queryAPI.TermQueryAPI - ---------- TermQueryAPI id 7 score 1.0 source {country=西班牙, name=哈维, club=巴萨罗那俱乐部}

8.2 数字和日期类型字段

与范围查询(Range Query)的around比较类似。形成在指定值上上下波动fuzziness大小的一个范围:

  1. -fuzziness <= field value <= +fuzziness

下面代码在18岁上下波动2岁,形成[17-19]的一个范围查询:

  1.    /**
  2.     * 模糊查询 数值型
  3.     * @param client
  4.     * @param index
  5.     * @param type
  6.     */
  7.    public static void fuzzyQuery2(Client client, String index, String type){
  8.        // Query
  9.        FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("age", "18");
  10.        fuzzyQueryBuilder.fuzziness(Fuzziness.TWO);
  11.        // Search
  12.        SearchRequestBuilder searchRequestBuilder = client.prepareSearch(index);
  13.        searchRequestBuilder.setTypes(type);
  14.        searchRequestBuilder.setQuery(fuzzyQueryBuilder);
  15.        // 执行
  16.        SearchResponse searchResponse = searchRequestBuilder.get();
  17.        // 结果
  18.        queryResult(searchResponse);
  19.    }

参考:https://www.elastic.co/guide/en/elasticsearch/reference/2.4/query-dsl-fuzzy-query.html


9. 说明

本代码基于ElasticSearch 2.4.1 







版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

elasticsearch__5__java操作之FilterBuilders构建过滤器Query

内容涉及代码GitHub地址:https://github.com/xiaohulu/util_xiaohulu/tree/master/src/com/elasticsearch 官方API:h...

分布式搜索Elasticsearch——QueryBuilders.matchPhrasePrefixQuery

注:该文项目基础为分布式搜索Elasticsearch——项目过程(一)和分布式搜索Elasticsearch——项目过程(二),项目骨架可至这里下载。         ES源代码中对match...
  • geloin
  • geloin
  • 2013-05-17 13:45
  • 4887

elasticsearch API 集合

3.3.1 Preparing a query 准备查询请求 import org.elasticsearch.action.search.SearchResponse; import ...
  • swcj
  • swcj
  • 2016-08-16 14:51
  • 1060

Elasticsearch Java API(七)--多级嵌套搜索

要在java中实现一个有三级父子关系的嵌套搜索,相关资料很少,发在stackoverflow上以后一个Switzerland的大神很快回复了我,google+stackoverflow很好使。对应的命...
  • napoay
  • napoay
  • 2016-07-29 04:44
  • 6160

ElasticSearch 入门

1、介绍ElasticSearch是一个基于 Apache Lucene(TM) 的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。但是...

elasticsearch__4__java操作之QueryBuilders构建搜索Query

内容涉及代码GitHub地址:https://github.com/xiaohulu/util_xiaohulu/tree/master/src/com/elasticsearch 官方API:h...

Elasticsearch笔记五之java操作es

java操作es集群代码
  • ty4315
  • ty4315
  • 2016-09-04 19:50
  • 19687

elasticsearch--搜索_Java基础使用

如转载请申明来源一、搜索示例a) 测试数据准备curl -XPUT localhost:9200/my_index/my_type/_bulk -d ' { "index": { "_id": 1 }...

elasticsearch中数据的插入与查询

public class ClientFactory { private String clusterName="elasticsearch"; private String addr...

ElasticSearch的基本用法与集群搭建

一、简介 ElasticSearch和Solr都是基于Lucene的搜索引擎,不过ElasticSearch天生支持分布式,而Solr是4.0版本后的SolrCloud才是分布式版本,Solr的...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)