1. 程式人生 > >Elasticsearch + MySQL實現LIKE %XX%效能優化

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<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全模糊查詢功能。
當然,針對具體的需求,還需要做一些調整,比如大小寫、分詞等等。