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工具类使用 

3. 测试每个方法的测试类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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值