首頁>技術>

需求分析:

在javashop電商系統中,商品資料是存在elasticsearch中,使用ik分詞器分詞,ik分詞器的詞庫內建了2萬多個。

但在實際運維過程中,因為商品的個性化,詞庫不一定可以滿足,為了搜尋引擎分詞(關鍵詞)更加準確,要求可對分詞詞庫進行手工維護。

思路:

IK自定義詞庫是支援遠端熱載入的。

先看下官方的說明:

remote_ext_dict:

1.該 http 請求需要返回兩個頭部(header),一個是 Last-Modified,一個是 ETag,這兩者都是字串型別,只要有一個發生變化,該外掛就會去抓取新的分詞進而更新詞庫。

2.該 http 請求返回的內容格式是一行一個分詞,換行符用 \\n 即可。

滿足上面兩點要求就可以實現熱更新分詞了,不需要重啟 ES 例項。

由此,我們可以開放一個API供IK呼叫。

搜尋分詞(關鍵詞)架構思路

1.管理端對關鍵詞進行維護;

2.管理端設定祕鑰(此祕鑰僅做載入分詞API驗證使用);

3.管理端展示分詞列表,根據最後修改時間倒序展示。

資料結構:

關鍵詞表(es_custom_words):

祕鑰設定說明: 在系統設定表(es_setting)中新增分組(ES_SIGN),對祕鑰進行維護時修改此分組下的資料。

領域模型管理端

管理端新增搜尋設定選單,對關鍵詞進行維護

模型

ES載入詞庫API

在基礎API中新增載入詞庫API,此Api需要校驗祕鑰,失敗返回空字串,成功則從資料庫中載入資料並返回。

IK Analyzer 擴充套件配置如下:

base-api-domain改為自己的base-api域名或者IP:埠即可

原始碼

​說明:此處僅展示IK載入片段程式碼,關於管理分此維護相關不做展示

CustomWordsBaseController

package com.enation.app.javashop.base.api;import com.enation.app.javashop.core.base.SettingGroup;import com.enation.app.javashop.core.client.system.SettingClient;import com.enation.app.javashop.core.goods.GoodsErrorCode;import com.enation.app.javashop.core.goodssearch.model.EsSecretSetting;import com.enation.app.javashop.core.goodssearch.service.CustomWordsManager;import com.enation.app.javashop.framework.exception.ServiceException;import com.enation.app.javashop.framework.util.JsonUtil;import com.enation.app.javashop.framework.util.StringUtil;import io.swagger.annotations.Api;import io.swagger.annotations.ApiImplicitParam;import io.swagger.annotations.ApiImplicitParams;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;import springfox.documentation.annotations.ApiIgnore;/** * 自定義分詞控制器 * * @author liuyulei * @version v1.0 * @since v7.0.0 * 2019-05-26 */@RestController@RequestMapping("/load-customwords")@Api(description = "載入分詞庫")public class CustomWordsBaseController {    @Autowired    private CustomWordsManager customWordsManager;    @Autowired    private SettingClient settingClient;    @GetMapping    @ApiImplicitParams({            @ApiImplicitParam(name = "secret_key", value = "祕鑰", required = true, dataType = "String", paramType = "query")    })    public String getCustomWords(@ApiIgnore  String secretKey){        if(StringUtil.isEmpty(secretKey)){            return "";        }        String value = settingClient.get(SettingGroup.ES_SIGN);        if(StringUtil.isEmpty(value)){            return "";        }        EsSecretSetting secretSetting = JsonUtil.jsonToObject(value,EsSecretSetting.class);        if(!secretKey.equals(secretSetting.getSecretKey())){            throw new ServiceException(GoodsErrorCode.E310.code(),"祕鑰驗證失敗!");        }        String res = this.customWordsManager.deploy();        try {            return new String(res.getBytes(),"utf-8");        }catch (Exception e){            e.printStackTrace();        }        return "";    }}

CustomWordsManager

package com.enation.app.javashop.core.goodssearch.service;/** * 自定義分詞表業務層 * @author fk * @version v1.0 * @since v7.0.0 * 2018-06-20 16:08:07 * * * update by liuyulei 2019-05-27 */public interface CustomWordsManager    {   /**    * 部署替換    * @return    */    String deploy();}

CustomWordsManagerImpl

package com.enation.app.javashop.core.goodssearch.service.impl;import com.enation.app.javashop.core.goodssearch.model.CustomWords;import com.enation.app.javashop.core.goodssearch.service.CustomWordsManager;import com.enation.app.javashop.framework.context.ThreadContextHolder;import com.enation.app.javashop.framework.database.DaoSupport;import com.enation.app.javashop.framework.util.DateUtil;import com.enation.app.javashop.framework.util.StringUtil;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Service;import javax.servlet.http.HttpServletResponse;import java.text.SimpleDateFormat;import java.util.List;/** * 自定義分詞表業務類 * * @author fk * @version v1.0 * @since v7.0.0 * 2018-06-20 16:08:07 * * update by liuyulei 2019-05-27 */@Servicepublic class CustomWordsManagerImpl implements CustomWordsManager {    @Autowired    @Qualifier("goodsDaoSupport")    private DaoSupport daoSupport;    @Override    public String deploy() {        String sql = "select * from es_custom_words where disabled = 1 order by modify_time desc";        List<CustomWords> list = this.daoSupport.queryForList(sql, CustomWords.class);        HttpServletResponse response = ThreadContextHolder.getHttpResponse();        StringBuffer buffer = new StringBuffer();        if (StringUtil.isNotEmpty(list)) {            int i = 0;            for (CustomWords word : list) {                if (i == 0) {                    SimpleDateFormat format =   new SimpleDateFormat( "yyyy-MM-dd hh:mm:ss" );                    try {                        response.setHeader("Last-Modified", format.parse(DateUtil.toString(word.getAddTime(),"yyyy-MM-dd hh:mm:ss")) + "");                        response.setHeader("ETag", format.parse(DateUtil.toString(word.getModifyTime(),"yyyy-MM-dd hh:mm:ss")) + "");                    }catch (Exception e){                        e.printStackTrace();                    }                    buffer.append(word.getName());                } else {                    buffer.append("\\n" + word.getName());                }                i++;            }        }        return buffer.toString();    }} 

以上為此次分享內容,後續每週會不定期分享架構文章,大家可以關注我們!!!

最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • FastApi誕生的緣由