Elasticsearch + MySQL实现LIKE %XX%性能优化

Elasticsearch安装(ECS-linux + elasticsearch-5.6.1)

  1. 下载安装包(elasticsearch-5.6.1.tar.gz)
  2. 上传安装包至远程服务器(ECS)
  3. 解压文件
  4. 修改配置(具体修改我也是百度的)
  5. root新增es用户,并赋予权限(elasticsearch无法用root直接启动)
  6. 启动(服务启动,后台运行)

定义数据结构

{
    id : '10000',
    tablename : 'product',
    filedname : 'productname',
    desc : 'test12345'
}

数据初始化

    // PO
    @ElasticEntity // 标识实体是否使用elasticsearch
    public class Product {
        private Long id;
        @ElasticEntity // 标识字段是否使用elasticsearch
        private String productName;
    }
    // 数据保存初始化数据到es服务器(单个)
    public static void put(Object entity) {
        Class classOfT = entity.getClass();
        // 判断是否是需同步ES的对象
        if (classOfT.isAnnotationPresent(ElasticEntity.class)) {
            Client client = getClient();
            Mirror mirror = Mirror.me(classOfT);
            String tableName = EntityUtil.getTableName(mirror);
            Object idValue = EntityUtil.getIdValue(mirror, entity);
            // 批量创建请求
            BulkRequestBuilder request = client.prepareBulk();
            // 获取需同步ES的对象字段
            Map field2DescMap = getEsColumns(mirror, entity);
            for (Map.Entry entry : field2DescMap.entrySet()) {
                if (StringUtil.isNotBlank(entry.getValue())) {
                    request.add(buildIndex(idValue, tableName, entry.getKey(), client)
                            .setSource(buildSource(idValue, tableName, entry.getKey(), entry.getValue())));
                }
            }
            if (request.numberOfActions() > 0) {
                request.execute().actionGet();
            }
        }
    }

数据查询

    // 单个字段搜索Elasticsearch
    public static List search(Class clazz, String searchStr, String fieldName) {
        List ids = new ArrayList();
        Client client = null;
        try {
            client = getClient();
            Mirror mirror = Mirror.me(clazz);
            // 表名
            String tableName = EntityUtil.getTableName(mirror);
            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
            if (StringUtil.isNotBlank(searchStr)) {
                queryBuilder.must(QueryBuilders.termQuery("tablename", tableName.toLowerCase()));
                queryBuilder.must(QueryBuilders.wildcardQuery("desc", "*" + searchStr.toLowerCase() + "*"));
                if (StringUtil.isNotEmpty(fieldName)) {
                    queryBuilder.must(QueryBuilders.termQuery("fieldname", fieldName.toLowerCase()));
                }
                SearchResponse searchResponse = client.prepareSearch(Constant.ES_INDEX).setTypes(Constant.ES_TYPE)
                        .setSize(ES_RETURN_SIZE).setQuery(queryBuilder).execute().actionGet();
                SearchHit[] searchHists = searchResponse.getHits().getHits();
                for (SearchHit hit : searchHists) {
                    ids.add((String) hit.getSource().get("id"));
                }
            }
        } catch (Exception e) {
            log.error("ES search failed", e);
        }
        return ids;
    }

    // mysql查询 + es查询
    String searchStr = "test";
    List ids = ElasticSearchUtil.search(Product.class, searchStr, "productName");
    if (ids != null && ids.size() > 0) {
        // 替换掉原来的 "AND a.productName LIKE '%' + searchStr + '%'"
        sq.appendSql(" AND a.productId IN (:espgIds)", true);
        sq.addParam("espgIds", ids, true);
    } else {
        sq.appendSql(" AND :noauth != :noauth", true);
        sq.addParam("noauth", 1, true);
    }

至此,基本完成Elasticsearch + MySQL实现LIKE全模糊查询功能。
当然,针对具体的需求,还需要做一些调整,比如大小写、分词等等。

你可能感兴趣的:(Elasticsearch + MySQL实现LIKE %XX%性能优化)