Browse Source

关键词,热词搜索更新等

chenyongxing 6 years ago
parent
commit
45b0df6e82

+ 4 - 0
src/main/java/com/yihu/ehr/resource/constants/MicroServiceApi.java

@ -12,4 +12,8 @@ public interface MicroServiceApi {
        String DICT_ENTRY = "cache/dict-entry";
        String DICT_ENTRIES = "cache/dict-entries";
    }
    interface ProfileSearch {
        String Hotwords = "/resource/hotwords";
    }
}

+ 27 - 0
src/main/java/com/yihu/ehr/resource/controller/TextSearchEndPoint.java

@ -5,6 +5,8 @@ import com.yihu.ehr.controller.EnvelopRestEndPoint;
import com.yihu.ehr.hbase.HBaseDao;
import com.yihu.ehr.profile.core.ResourceCore;
import com.yihu.ehr.profile.family.ResourceCells;
import com.yihu.ehr.resource.constants.MicroServiceApi;
import com.yihu.ehr.resource.service.ProfileSearchService;
import com.yihu.ehr.solr.SolrUtil;
import com.yihu.ehr.util.rest.Envelop;
import io.swagger.annotations.Api;
@ -36,6 +38,8 @@ public class TextSearchEndPoint extends EnvelopRestEndPoint {
    private SolrUtil solrUtil;
    @Autowired
    private HBaseDao hBaseDao;
    @Autowired
    private ProfileSearchService profileSearchService;
    @ApiOperation(value = "全文检索")
    @RequestMapping(value = "/resources/text/search", method = RequestMethod.GET)
@ -49,6 +53,8 @@ public class TextSearchEndPoint extends EnvelopRestEndPoint {
        if (page == 0) {
            page ++;
        }
        //更新热搜
        profileSearchService.saveOrUpdateHotWords(keyword, 1);
        Map<String, String> sortMap = new HashMap<>(1);
        sortMap.put(ResourceCells.EVENT_DATE, "desc");
        QueryResponse queryResponse = solrUtil.highlight(ResourceCore.MasterTable, generateQ(keyword), null, sortMap, page - 1, size, ResourceCells.SEARCH_FIELD, null);
@ -81,6 +87,27 @@ public class TextSearchEndPoint extends EnvelopRestEndPoint {
        return success(dataList, (int)queryResponse.getResults().getNumFound(), page, size);
    }
    @ApiOperation("获取热搜")
    @RequestMapping(value = MicroServiceApi.ProfileSearch.Hotwords, method = RequestMethod.GET)
    public List<String> getHotWords(
            @ApiParam(name = "reCount", value = "返回个数", required = true)
            @RequestParam(value = "reCount") int reCount,
            @ApiParam(name = "type", value = "类型,1:病人档案热搜", required = true)
            @RequestParam(value = "type") int type){
        List<String> hotWords = profileSearchService.getHotWords(type,reCount);
        return hotWords;
    }
    @ApiOperation("更新热搜")
    @RequestMapping(value = MicroServiceApi.ProfileSearch.Hotwords, method = RequestMethod.POST)
    public boolean updateHotWords(
            @ApiParam(name = "searchText", value = "搜索关键词", required = true)
            @RequestParam(value = "searchText") String searchText,
            @ApiParam(name = "type", value = "类型,1:病人档案热搜", required = true)
            @RequestParam(value = "type") int type){
        return profileSearchService.saveOrUpdateHotWords(searchText,type);
    }
    private String generateQ(String keyword) {
        if (StringUtils.isEmpty(keyword)) {
            return "*:*";

+ 13 - 0
src/main/java/com/yihu/ehr/resource/dao/HotWordDao.java

@ -0,0 +1,13 @@
package com.yihu.ehr.resource.dao;
import com.yihu.ehr.resource.model.HotWord;
import org.springframework.data.repository.PagingAndSortingRepository;
/**
 * @author linaz
 * @created 2016.05.12 8:53
 */
public interface HotWordDao extends PagingAndSortingRepository<HotWord,String> {
}

+ 41 - 0
src/main/java/com/yihu/ehr/resource/job/HotWordsTask.java

@ -0,0 +1,41 @@
package com.yihu.ehr.resource.job;
import com.yihu.ehr.resource.service.ProfileSearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Set;
@Component
public class HotWordsTask {
    @Autowired
    private ProfileSearchService profileSearchService;
    @Autowired
    private RedisTemplate redisTemplate;
    private static final String LOCK = "SYSN_HOTWORDS_LOCK";
    private static final String KEY = "SYSN_HOTWORDS_KEY";
    @Scheduled(cron = "0 0 1 * * ?")
    private void startTask(){
        boolean lock = false;
        try {
            lock = redisTemplate.opsForValue().setIfAbsent(KEY, LOCK);
            if (lock) {
                profileSearchService.synRedisHotWords(1);
            }
        } finally {
            if (lock) {
                redisTemplate.delete(KEY);
            }
        }
    }
}

+ 77 - 0
src/main/java/com/yihu/ehr/resource/model/HotWord.java

@ -0,0 +1,77 @@
package com.yihu.ehr.resource.model;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.hibernate.annotations.GenericGenerator;
import javax.persistence.*;
import java.util.Date;
@Entity
@Table(name="hot_word")
public class HotWord {
    private String id;
    private String word;
    private int searchCount;
    private long expireTime;
    private int type;
    private Date updateTime;
    @Id
    @GenericGenerator(name="idGenerator", strategy="uuid")
    @GeneratedValue(generator="idGenerator")
    @Column(name = "id", unique = true, nullable = false,length = 32)
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    @Column(name = "word", nullable = false)
    public String getWord() {
        return word;
    }
    public void setWord(String word) {
        this.word = word;
    }
    @Column(name = "search_count", nullable = false)
    public int getSearchCount() {
        return searchCount;
    }
    public void setSearchCount(int searchCount) {
        this.searchCount = searchCount;
    }
    @Column(name = "expire_time", nullable = false)
    public long getExpireTime() {
        return expireTime;
    }
    public void setExpireTime(long expireTime) {
        this.expireTime = expireTime;
    }
    @Column(name = "type", nullable = false)
    public int getType() {
        return type;
    }
    public void setType(int type) {
        this.type = type;
    }
    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @Column(name = "update_time", nullable = false)
    public Date getUpdateTime() {
        return updateTime;
    }
    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }
}

+ 125 - 0
src/main/java/com/yihu/ehr/resource/service/ProfileSearchService.java

@ -0,0 +1,125 @@
package com.yihu.ehr.resource.service;
import com.yihu.ehr.query.BaseJpaService;
import com.yihu.ehr.resource.dao.HotWordDao;
import com.yihu.ehr.resource.model.HotWord;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
@Service
@Transactional
public class ProfileSearchService extends BaseJpaService<HotWord,HotWordDao> {
    private static final String PrefixRedis = "HOTWORDS_";
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private JdbcTemplate jdbcTemplate;
    public boolean saveOrUpdateHotWords(String searchText,int type){
        boolean b = false;
        if(StringUtils.isNotBlank(searchText)){
            List<String> searchKeyWords = getSearchKeyWords(searchText);
            b = saveOrUpdateToRedis(searchKeyWords,type);
        }
        return b;
    }
    public List<String> getHotWords(int type,int recount){
        List<String> result = new ArrayList<>();
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        Set<String> values = zSetOperations.reverseRangeByScore(PrefixRedis+type, 0, Double.MAX_VALUE);
        if(recount <= 0){
            return result;
        }
        if(values.size() > 0){
            for(String value:values){
                result.add(value);
                if(result.size() == recount){
                    return result;
                }
            }
        }else{
            //查看数据库是否有值,防止redis数据丢失
            List<Map<String, Object>> list = jdbcTemplate.queryForList("select * from hot_word where type=" + type + " order by search_count desc");
            if(CollectionUtils.isNotEmpty(list)){
                //不为空,将数据同步到redis,并返回数据
                for(Map<String,Object> map:list){
                    zSetOperations.incrementScore(PrefixRedis+type, map.get("word"), Double.valueOf(map.get("search_count")+""));
                    if(result.size() < recount){
                        result.add(map.get("word")+"");
                    }
                }
            }
        }
        return result;
    }
    private List<String> getSearchKeyWords(String keys){
        List<String> list = new ArrayList<>();
        if(StringUtils.isNotBlank(keys)){
            String[] keyArray = keys.split(" ");
            for(String key:keyArray){
                if(StringUtils.isNotBlank(key) && !"or".equalsIgnoreCase(key) && !"and".equalsIgnoreCase(key)){
                    if(key.startsWith("\"") && key.endsWith("\"")){
                        key = key.substring(1,key.length()-1);
                    }else if(key.startsWith("+") || key.startsWith("-")){
                        key = key.substring(1);
                    }
                    list.add(key);
                }
            }
        }
        return list;
    }
    /**
     *
     * @param keys 搜索词
     * @param type 1:病历(目前只有该分类,用于后期做扩展)
     * @return
     */
    public boolean saveOrUpdateToRedis(List<String> keys,int type){
        if(CollectionUtils.isNotEmpty(keys)){
            keys.forEach(key ->{
                ZSetOperations zSetOperations = redisTemplate.opsForZSet();
                zSetOperations.incrementScore(PrefixRedis+type, key, 1);
            });
        }
        return true;
    }
    public boolean synRedisHotWords(int type){
        //1.获取redis中的热搜
        ZSetOperations zSetOperations = redisTemplate.opsForZSet();
        Set<ZSetOperations.TypedTuple<String>> values = zSetOperations.rangeByScoreWithScores(PrefixRedis+type, 0, Double.MAX_VALUE);
        Date now = new Date();
        if(!values.isEmpty()){
            //2.清空mysql的热搜
            jdbcTemplate.execute("delete from hot_word where type ="+type);
            List<HotWord> insertList = new ArrayList<>();
            for(ZSetOperations.TypedTuple value:values){
                HotWord hotWord = new HotWord();
                hotWord.setWord(value.getValue().toString());
                hotWord.setSearchCount((int)value.getScore().doubleValue());
                hotWord.setExpireTime(-1);
                hotWord.setType(type);
                hotWord.setUpdateTime(now);
                insertList.add(hotWord);
            }
            batchInsert(insertList);
        }
        return true;
    }
}