雖然docker方便.但是由于163鏡像版本太低.所以在本地搭了一個es.版本6.3.0;
首先說下這次研究的方向: 搜索框搜西紅柿,那么番茄是出不來的. 搜索米的時候.蝦米條比大米的相關(guān)度還高
暫時考慮的方案如下:
1.加入同義詞
2.相關(guān)度優(yōu)化.將字段排優(yōu)先級,名字的相關(guān)度提升
3.未雨綢繆,增加類似某寶某東一樣的,銷量高的排名也提升一點,具體如下
同義詞插件
插件1 :同義詞文件配置方式
插件2 :數(shù)據(jù)庫配置方式
原本想使用插件2. 兩種方式都是可以動態(tài)加載同義詞詞庫.所以配置好之后不需要修改詞庫就重啟es,
但是插件2的大佬一直沒有更新,所以我在6.3.0中加入插件報錯我沒有處理好暫時先使用插件1
插件2
項目支持6.x版本.但是tag上沒有,因此clone到本地.修改版本.然后maven打包.得到插件放到es的plugins下重啟es
github上有使用的實例.我的測試用例,這個成功之后,暫時先放一邊.先搞下相關(guān)度優(yōu)化
DELETE prod
PUT /prod
{
"index" : {
"analysis" : {
"analyzer" : {
"synonym" : {
"tokenizer" : "ik_max_word",
"filter" : ["remote_synonym"]
}
},
"filter" : {
"remote_synonym" : {
"type" : "dynamic_synonym",
"synonyms_path" : "synonym.txt", //文件沒有就創(chuàng)建一個
"interval": 30 //由于本地跑.所以30s重新查一次.線上肯定不可以30s
},
"local_synonym" : {
"type" : "dynamic_synonym",
"synonyms_path" : "synonym.txt"
}
}
}
}
}
將項目中需要優(yōu)化的幾個字段抽取出來自己定義了一個精簡版的demo
PUT /prod/demo/_mapping
{
"properties":{
"name":{
"type":"text",
"analyzer": "synonym"
},
"description":{
"type":"text",
"analyzer": "ik_max_word"
},
"brandName":{
"type":"text",
"analyzer": "ik_max_word"
},
"labelName": {
"type": "text",
"analyzer": "ik_max_word"
},
"menuCategoryNamePath": {
"type": "text",
"analyzer": "ik_max_word"
},
"num":{
"type": "integer"
}
}
}
原先的查詢代碼:
QueryBuilders.multiMatchQuery(((SearchProductReq) req).getSearchContent(),
PRODUCT_NAME,
BRAND_NAME,
DESCRIPTION,
LABEL_NAME,
MENU_CATEGORY_NAME_PATH);
等同于:
GET prod/demo/_search
{
"query":{
"multi_match": {
"query": "米",
"fields": ["name","description","brandName","labelName","menuCategoryNamePath"]
}
}
}
修改后,排分還待修正.暫時按這樣的分?jǐn)?shù):
QueryBuilder queryBuilder = QueryBuilders.boolQuery()
.should(QueryBuilders.matchQuery("name", "米").boost(0.8f))
.should(QueryBuilders.matchQuery("brandName", "米").boost(0.6f))
.should(QueryBuilders.matchQuery("labelName", "米").boost(0.6f))
.should(QueryBuilders.matchQuery("menuCategoryNamePath", "米").boost(0.2f))
.should(QueryBuilders.matchQuery("description", "米").boost(0.4f));
FieldValueFactorFunctionBuilder factorFunctionBuilder = new FieldValueFactorFunctionBuilder("num");
factorFunctionBuilder.factor(0.1f);
factorFunctionBuilder.modifier(FieldValueFactorFunction.Modifier.LOG1P);
FunctionScoreQueryBuilder boostMode = QueryBuilders
.functionScoreQuery(queryBuilder, factorFunctionBuilder)
.boostMode(CombineFunction.SUM);
SearchRequestBuilder requestBuilder = client.prepareSearch(ESConstant.PRODUCT_INDEX)
.setTypes(ESConstant.PRODUCT_TYPE);
requestBuilder.setQuery(boostMode);
等同于:
GET prod/demo/_search
{
"query":{
"function_score": {
"query": {
"bool": {
"should": [
{
"match": {
"name": {"query": "大米","boost":0.8}
}
},
{
"match": {
"brandName": {"query": "大米","boost":0.6}
}
},
{
"match": {
"labelName": {"query": "大米","boost":0.6}
}
},
{
"match": {
"description": {"query": "大米","boost":0.5}
},
{
"match": {
"menuCategoryNamePath": {"query": "大米","boost":0.2}
}
}
]
}
},
"field_value_factor": {
"field": "num",
"modifier": "log1p",
"factor": 0.1
},
"boost_mode": "sum"
}
}
}
提升相關(guān)度使用function_score參考官方文檔
加入同義詞,這個需要修改mapping.
PUT /prod/demo/_mapping
{
"properties":{
"name":{
"type":"text",
"analyzer": "synonym"
},
"description":{
"type":"text",
"analyzer": "synonym"
},
"brandName":{
"type":"text",
"analyzer": "synonym"
},
"labelName": {
"type": "text",
"analyzer": "synonym"
},
"menuCategoryNamePath": {
"type": "text",
"analyzer": "synonym"
},
"num":{
"type": "integer"
}
}
}
這時候在config的synonym.txt文件中增加同義詞.比如比如插入數(shù)據(jù):
POST /prod/demo/2
{
"name":"大米",
"description":"稻香大米",
"brandName":"COCO",
"labelName":"大米",
"menuCategoryNamePath":"食品|飲料",
"num":3
}
POST /prod/demo/3
{
"name":"蝦米條",
"description":"蝦米條",
"brandName":"COCO",
"labelName":"蝦米條",
"menuCategoryNamePath":"食品|零食",
"num":1
}
POST /prod/demo/4
{
"name":"惠宜 珍珠米 10KG",
"description":"惠宜 珍珠米 10KG",
"brandName":"COCO",
"labelName":"惠宜",
"menuCategoryNamePath":"食品|飲料",
"num":5
}
POST /prod/demo/5
{
"name":"口口牌 泰國進口 泰國茉莉香米",
"description":"口口牌 泰國進口 泰國茉莉香米",
"brandName":"COCO",
"labelName":"口口牌",
"menuCategoryNamePath":"食品|飲料",
"num":3
}
ik分詞器不會拆大米.所以大米和米是兩個條件. 如果把米/大米設(shè)置成近義詞.name這時候.搜米和大米都能收到上述商品.并且相關(guān)度也有有一定變化.
首先沒有淘寶京東那么智能,但是由于我剛接觸es.暫時先這樣優(yōu)化下,
測試數(shù)據(jù).很假,主要測試下效果.