elasticsearch同義詞和搜索相關(guān)度優(yōu)化

雖然docker方便.但是由于163鏡像版本太低.所以在本地搭了一個(gè)es.版本6.3.0;

首先說下這次研究的方向: 搜索框搜西紅柿,那么番茄是出不來的. 搜索米的時(shí)候.蝦米條比大米的相關(guān)度還高
暫時(shí)考慮的方案如下:
1.加入同義詞
2.相關(guān)度優(yōu)化.將字段排優(yōu)先級(jí),名字的相關(guān)度提升
3.未雨綢繆,增加類似某寶某東一樣的,銷量高的排名也提升一點(diǎn),具體如下


同義詞插件

插件1 :同義詞文件配置方式
插件2 :數(shù)據(jù)庫(kù)配置方式
原本想使用插件2. 兩種方式都是可以動(dòng)態(tài)加載同義詞詞庫(kù).所以配置好之后不需要修改詞庫(kù)就重啟es,
但是插件2的大佬一直沒有更新,所以我在6.3.0中加入插件報(bào)錯(cuò)我沒有處理好暫時(shí)先使用插件1

插件2
項(xiàng)目支持6.x版本.但是tag上沒有,因此clone到本地.修改版本.然后maven打包.得到插件放到es的plugins下重啟es
github上有使用的實(shí)例.我的測(cè)試用例,這個(gè)成功之后,暫時(shí)先放一邊.先搞下相關(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)建一個(gè)
                    "interval": 30          //由于本地跑.所以30s重新查一次.線上肯定不可以30s
                },
                "local_synonym" : {
                    "type" : "dynamic_synonym",
                    "synonyms_path" : "synonym.txt"
                }
            }
        }
    }
}


將項(xiàng)目中需要優(yōu)化的幾個(gè)字段抽取出來自己定義了一個(gè)精簡(jiǎn)版的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"]
    }
  }
}

修改后,排分還待修正.暫時(shí)按這樣的分?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參考官方文檔


加入同義詞,這個(gè)需要修改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"
        }
  }
}

這時(shí)候在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":"口口牌 泰國(guó)進(jìn)口 泰國(guó)茉莉香米",
   "description":"口口牌 泰國(guó)進(jìn)口 泰國(guó)茉莉香米",
    "brandName":"COCO",
    "labelName":"口口牌",
    "menuCategoryNamePath":"食品|飲料",
     "num":3
}

ik分詞器不會(huì)拆大米.所以大米和米是兩個(gè)條件. 如果把米/大米設(shè)置成近義詞.name這時(shí)候.搜米和大米都能收到上述商品.并且相關(guān)度也有有一定變化.

首先沒有淘寶京東那么智能,但是由于我剛接觸es.暫時(shí)先這樣優(yōu)化下,
測(cè)試數(shù)據(jù).很假,主要測(cè)試下效果.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容