ES6.6.2 使用小结 - 封装ES常用的查询方法
1.首先,接下来的查询demo里面包含了10常用的方法:term查询、terms查询、range查询、exists查询、prefix查询、wildcard查询、regexp查询、fuzzy查询、type查询、ids查询。
2.以下是封装了10个常用方法的QueryUtil:
package com.bas.util;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.index.query.QueryBuilder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class QueryUtil {
private static SearchHits hits;
private static TransportClient client = ESUtil.getClient();
/**
* 打印常见信息
*/
public static void print() {
if (hits == null) {
return;
}
System.out.println("-> totalHits: "+hits.totalHits);
for (SearchHit hit : hits) {
System.out.println("-----------");
System.out.println("source:" + hit.getSourceAsString());
System.out.println("index:" + hit.getIndex());
System.out.println("type:" + hit.getType());
System.out.println("id:" + hit.getId());
//遍历文档的每个字段
Map<String, Object> map = hit.getSourceAsMap();
for (String key : map.keySet()) {
System.out.println(key + "=" + map.get(key));
}
System.out.println("HighlightFields:" + hit.getHighlightFields());
System.out.println("Fields:" + hit.getFields());
System.out.println("MatchedQueries:" + hit.getMatchedQueries());
System.out.println("InnerHits:" + hit.getInnerHits());
System.out.println("-----------");
}
}
/**
* 执行查询
*
* @param query 查询器
* @return 当前查询对象
*/
private static List<Map<String, Object>> executeQuery(QueryBuilder query, String indexName, int size) {
//搜索结果存入SearchResponse
SearchResponse response = client.prepareSearch(indexName)
.setQuery(query) //设置查询器
.setSize(size) //一次查询文档数
.get();
hits = response.getHits();
if (hits == null) {
return null;
}
List<Map<String, Object>> resultList = new ArrayList<>();
for (SearchHit hit : hits) {
resultList.add(hit.getSourceAsMap());
}
print();
return resultList;
}
/**
* Find documents which contain the exact term specified in the field specified.
* 单个精确词项查询,内容有中文不能匹配
* @param indexName 索引名
* @param size 数据量
* @param field 查询字段
* @param termValue 单个词项内容
* @return 结果集
*/
public synchronized static List<Map<String, Object>> termQuery(String indexName, int size, String field, String termValue) {
QueryBuilder qb = QueryBuilders.termQuery(field, termValue);
return executeQuery(qb, indexName, size);
}
/**
* Find documents which contain any of the exact terms specified in the field specified.
* 多个精确词项查询,内容有中文不能匹配
* @param indexName 索引名
* @param size 数据量
* @param field 查询字段
* @param termValue 单个词项内容
* @return 结果集
*/
public synchronized static List<Map<String, Object>> termsQuery(String indexName, int size, String field, String ...termValue) {
QueryBuilder qb = QueryBuilders.termsQuery(field, termValue);
return executeQuery(qb, indexName, size);
}
/**
* Find documents where the field specified
* contains values (dates, numbers, or strings) in the range specified.
* @param indexName 索引名
* @param size 数据量
* @param field 查询字段
* @param from 起始时间
* @param to 截止时间
* @return 结果集
*/
public synchronized static List<Map<String, Object>> rangeQuery(String indexName, int size, String field, String from, String to) {
QueryBuilder qb = QueryBuilders.rangeQuery(field).from(from).to(to);
return executeQuery(qb, indexName, size);
}
/**
* Find documents where the field specified contains any non-null value.
* 查找包含任何非空值的文档的指定字段
* @param indexName 索引名
* @param size 数据量
* @param field 查询字段
* @return 结果集
*/
public synchronized static List<Map<String, Object>> existsQuery(String indexName, int size, String field) {
QueryBuilder qb = QueryBuilders.existsQuery(field);
return executeQuery(qb, indexName, size);
}
/**
* Find documents where the field specified contains terms
* which being with the exact prefix specified.
* 匹配包含xx前缀的文档,内容有中文不能匹配
* @param indexName 索引名
* @param size 数据量
* @param field 查询字段
* @param prefixValue 前缀内容
* @return 结果集
*/
public synchronized static List<Map<String, Object>> prefixQuery(String indexName, int size, String field, String prefixValue) {
QueryBuilder qb = QueryBuilders.prefixQuery(field, prefixValue);
return executeQuery(qb, indexName, size);
}
/**
* Find documents where the field specified contains terms
* which match the pattern specified,
* where the pattern supports single character wildcards (?)
* and multi-character wildcards (*)
* 通配符匹配查询,内容有中文不能匹配
* @param indexName 索引名
* @param size 数据量
* @param field 查询字段
* @param wildcardValue 包含通配符的内容
* @return 结果集
*/
public synchronized static List<Map<String, Object>> wildcardQuery(String indexName, int size, String field, String wildcardValue) {
QueryBuilder qb = QueryBuilders.wildcardQuery(field, wildcardValue);
return executeQuery(qb, indexName, size);
}
/**
* Find documents where the field specified contains terms
* which match the regular expression specified.
* 正则匹配查询,内容有中文不能匹配
* @param indexName 索引名
* @param size 数据量
* @param field 查询字段
* @param regexpValue 包含正则的内容
* @return 结果集
*/
public synchronized static List<Map<String, Object>> regexpQuery(String indexName, int size, String field, String regexpValue) {
QueryBuilder qb = QueryBuilders.regexpQuery(field, regexpValue);
return executeQuery(qb, indexName, size);
}
/**
* Find documents where the field specified contains terms
* which are fuzzily similar to the specified term.
* Fuzziness is measured as a Levenshtein edit distance of 1 or 2.
* 模糊查询,内容有中文不能匹配
* @param indexName 索引名
* @param size 数据量
* @param field 查询字段
* @param fuzzyValue 模糊值
* @return 结果集
*/
public synchronized static List<Map<String, Object>> fuzzyQuery(String indexName, int size, String field, String fuzzyValue) {
QueryBuilder qb = QueryBuilders.fuzzyQuery(field, fuzzyValue);
return executeQuery(qb, indexName, size);
}
/**
* Find documents of the specified type.
* 查询指定type名的文档
* @param indexName 索引名
* @param size 数据量
* @param type type名
* @return 结果集
*/
public synchronized static List<Map<String, Object>> typeQuery(String indexName, int size, String type) {
QueryBuilder qb = QueryBuilders.typeQuery(type);
return executeQuery(qb, indexName, size);
}
/**
* Find documents with the specified type and IDs.
* 根据指定的type和文档id查询
* @param indexName 索引名
* @param size 数据量
* @param ids 文档的_id
* @return 结果集
*/
public synchronized static List<Map<String, Object>> idsQuery(String indexName, int size, String ...ids) {
QueryBuilder qb = QueryBuilders.idsQuery(ids);
return executeQuery(qb, indexName, size);
}
}
其中,ES工具类位于:ES6.6.2 使用小结 - ES工具类使用
测试每个方法的测试类MatchQueryDemo如下:
package com.bas.demo;
import com.bas.util.ESUtil;
import com.bas.util.QueryUtil;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.junit.jupiter.api.Test;import java.util.Map;
public class MatchQueryDemo {
/**
* 全量查询
*
* @param args
*/
public static void main(String[] args) {
TransportClient client = ESUtil.getClient();
//构造查询对象
QueryBuilder query = QueryBuilders.matchAllQuery();
//搜索结果存入SearchResponse
SearchResponse response = client.prepareSearch("app_account")
.setQuery(query) //设置查询器
.setSize(3) //一次查询文档数
.get();
SearchHits hits = response.getHits();
int count = 1;
for (SearchHit hit : hits) {
System.out.println("--------------------" + count++);
System.out.println("source:" + hit.getSourceAsString());
System.out.println("index:" + hit.getIndex());
System.out.println("type:" + hit.getType());
System.out.println("id:" + hit.getId());
//遍历文档的每个字段
Map<String, Object> map = hit.getSourceAsMap();
for (String key : map.keySet()) {
System.out.println(key + "=" + map.get(key));
}
System.out.println("--------------------\n");
}
}
/**
* 单个字段匹配查询
*/
@Test
public void matchQuery() {
SearchHits hits;
//构造查询对象
QueryBuilder query = QueryBuilders.matchQuery(
"title",
"标题");
SearchResponse response = ESUtil.getClient().prepareSearch("app_account")
.setQuery(query) //设置查询器
.setSize(5) //一次查询文档数
.get();
hits = response.getHits();
for (SearchHit hit : hits) {
System.out.println("source:" + hit.getSourceAsString());
System.out.println("index:" + hit.getIndex());
System.out.println("type:" + hit.getType());
System.out.println("id:" + hit.getId());
//遍历文档的每个字段
Map<String, Object> map = hit.getSourceAsMap();
for (String key : map.keySet()) {
System.out.println(key + "=" + map.get(key));
}
System.out.println("HighlightFields:" + hit.getHighlightFields());
System.out.println("Fields:" + hit.getFields());
System.out.println("MatchedQueries:" + hit.getMatchedQueries().length);
System.out.println("InnerHits:" + hit.getInnerHits());
}
}
/**
* 操作符查询
*/
@Test
public void operatorQuery() {
SearchHits hits;
//构造查询对象
QueryBuilder query = QueryBuilders.matchQuery(
"title",
"标题").operator(Operator.AND);
SearchResponse response = ESUtil.getClient().prepareSearch("app_account")
.setQuery(query) //设置查询器
.setSize(5) //一次查询文档数
.get();
hits = response.getHits();
for (SearchHit hit : hits) {
System.out.println("--------");
System.out.println("source:" + hit.getSourceAsString());
System.out.println("index:" + hit.getIndex());
System.out.println("type:" + hit.getType());
System.out.println("id:" + hit.getId());
//遍历文档的每个字段
Map<String, Object> map = hit.getSourceAsMap();
for (String key : map.keySet()) {
System.out.println(key + "=" + map.get(key));
}
System.out.println("HighlightFields:" + hit.getHighlightFields());
System.out.println("Fields:" + hit.getFields());
System.out.println("--------");
}
}
/**
* 多字段同时匹配查询
* 内容有中文不能匹配
*/
@Test
public void multiMatchQuery() {
SearchHits hits;
//构造查询对象
QueryBuilder query = QueryBuilders.multiMatchQuery(
"bas",
"title", "url");
SearchResponse response = ESUtil.getClient().prepareSearch("app_account")
.setQuery(query) //设置查询器
.setSize(5) //一次查询文档数
.get();
hits = response.getHits();
for (SearchHit hit : hits) {
System.out.println("source:" + hit.getSourceAsString());
System.out.println("index:" + hit.getIndex());
System.out.println("type:" + hit.getType());
System.out.println("id:" + hit.getId());
//遍历文档的每个字段
Map<String, Object> map = hit.getSourceAsMap();
for (String key : map.keySet()) {
System.out.println(key + "=" + map.get(key));
}
System.out.println("HighlightFields:" + hit.getHighlightFields());
System.out.println("Fields:" + hit.getFields());
}
}
/**
* 单个词项精确查询,内容有中文不能匹配
*/
@Test
public void termQuery() {
QueryUtil.termQuery("app_account", 5, "url", "bas");
}
/**
* 多个词项精确查询,内容有中文不能匹配
*/
@Test
public void termsQuery() {
// QueryUtil.termsQuery(“app_account”, 5, “title.keyword”, “更新title”, “标题”); // 这样就可以匹配中文了,或者修改mapping的字段属性为不分词
QueryUtil.termsQuery("app_account", 5, "title", "更新title", "标题");
}
@Test
public void rangeQuery() {
QueryUtil.rangeQuery("app_account", 100, "postdate", "2017-03-24", "2019-03-24");
}
@Test
public void existsQuery() {
QueryUtil.existsQuery("app_account", 100, "postdate");
}
/**
* 匹配包含xx前缀的文档,内容有中文不能匹配
*/
@Test
public void prefixQuery() {
// QueryUtil.prefixQuery(“app_account”, 100, “title.keyword”,”标题”); // 这样就可以匹配中文了
QueryUtil.prefixQuery("app_account", 100, "title.keyword", "标题");
}
/**
* 通配符匹配查询,内容有中文不能匹配
*/
@Test
public void wildcardQuery() {
// QueryUtil.wildcardQuery(“app_account”, 100, “title.keyword”, “标题*”);
QueryUtil.wildcardQuery("app_account", 100, "title", "标题*");
}
/**
* 正则匹配查询,内容有中文不能匹配
*/
@Test
public void regexpQuery() {
// QueryUtil.regexpQuery(“app_account”, 100, “title.keyword”, “标题.*”);
QueryUtil.regexpQuery("app_account", 100, "title", "标题.*");
}
/**
* 模糊查询,内容有中文不能匹配
* 字段名加上.keyword也不能匹配中文
*/
@Test
public void fuzzyQuery() {
// QueryUtil.fuzzyQuery(“app_account”, 100, “title.keyword”, “标题”);
QueryUtil.fuzzyQuery("app_account", 100, "title", "asd");
}
@Test
public void typeQuery() {
QueryUtil.typeQuery("app_account", 5, "blog");
}
@Test
public void idsQuery() {
QueryUtil.idsQuery("app_account", 5, "asdasdcVcCKaQfGQ3", "52AbtWkBqLTNcYM2gf0z", "62AltWkBqLTNcYM27f2h");
}
}
注:
1.应该会有不少人会发现,ES的查询器的有些方法可能会不能匹配中文,正如测试类的注释说的,在查询字段后加上:.keyword,如图:
2.如果不想每次增加.keyword来匹配中文内容,建立mapping 的时候可以设置”index”: “not_analyzed”,这样也可以实现。
附(两篇和ES常用方法的文章):
1.https://www.cnblogs.com/fclbky/p/7124469.html
2.https://www.jianshu.com/p/14ac79f93a38
还没有评论,来说两句吧...