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

来源:互联网 发布:网络打线钳 编辑:程序博客网 时间:2024/05/29 04:13

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<String, String> field2DescMap = getEsColumns(mirror, entity);            for (Map.Entry<String, String> 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<String> search(Class<?> clazz, String searchStr, String fieldName) {        List<String> ids = new ArrayList<String>();        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<String> 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全模糊查询功能。
当然,针对具体的需求,还需要做一些调整,比如大小写、分词等等。

原创粉丝点击