Elasticsearch + MySQL實現LIKE %XX%效能優化
阿新 • • 發佈:2019-01-28
Elasticsearch安裝(ECS-linux + elasticsearch-5.6.1)
- 下載安裝包(elasticsearch-5.6.1.tar.gz)
- 上傳安裝包至遠端伺服器(ECS)
- 解壓檔案
- 修改配置(具體修改我也是百度的)
- root新增es使用者,並賦予許可權(elasticsearch無法用root直接啟動)
- 啟動(服務啟動,後臺執行)
定義資料結構
{
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全模糊查詢功能。
當然,針對具體的需求,還需要做一些調整,比如大小寫、分詞等等。