热点平台搭建(四)——Springboot+Elasticsea

2020-03-11  本文已影响0人  请不要问我是谁

使用Elasticsearch查询历史热点消息,搜索的内容包括:根据关键词搜索,可以多个关键词;根据热点标题查找历史热度值变化。

搜索框DTO

用来接收前端传递的搜索框内容。

@Data
public class SearchKeywords {
    @NotEmpty
    private String keywords;
    @NotEmpty
    private String relation;
    @NotEmpty
    @NotNull
    private String type;
}

定义SeachData接收从ES返回的数据

@Data
@AllArgsConstructor
@NoArgsConstructor
public class SearchData {
    private String titleText;
    private String titleKeyword;
    private Integer rank;
    private Integer hotNumber;
    private String timestamp;
    private Integer uId;
}

服务接口

public interface SearchService {
    /**
     * 根据标题查找历史信息
     * @param title 标题
     * @param type 哪个表
     * @return 历史信息
     */
    public List<SearchData> searchByName(String title, String type);

    /**
     * 根据关键词查找
     * @param keyword 关键词
     * @param type 表名
     * @param relation 关键词之间的关系
     * @return 历史信息
     */
    public List<SearchData> searchByKeyword(String keyword, String type, String relation);

    /**
     * 根据uId查找内容详情
     * @param type 热榜名称
     * @param uId 唯一键
     * @return 详情
     */
    public List<SearchDetail> searchDetail(String type, int uId);
}

包括两个查询内容,还包含了一个根据uId查找历史消息,uId在数据库中建立了索引。

服务实现

@Service
public class SearchServiceImpl implements SearchService {

    @Autowired
    private EsUtil esUtil;

    @Autowired
    private SearchDetailMapper searchDetailMapper;

    @Override
    public List<SearchData> searchByName(String title, String type) {
        // 创建bool query
        BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
        // 查找title_keyword中有查找的关键词
        boolQueryBuilder.filter(QueryBuilders.termQuery("title_keyword", title));
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(boolQueryBuilder);
        // 根据时间倒序
        builder.sort("timestamp", SortOrder.ASC);
        // 取前30个
        builder.size(30);
        return esUtil.search(type+"_data", builder, SearchData.class);
    }

    @Override
    public List<SearchData> searchByKeyword(String keyword, String type, String relation) {
        // 创建simple query string
        SimpleQueryStringBuilder simpleQueryStringBuilder = new SimpleQueryStringBuilder(keyword);
        // 根据title_text匹配
        simpleQueryStringBuilder.field("title_text");
        // 关键词关系有和与或
        if("OR".equals(relation) || "or".equals(relation)){
            simpleQueryStringBuilder.defaultOperator(Operator.OR);
        }else {
            simpleQueryStringBuilder.defaultOperator(Operator.AND);
        }
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(simpleQueryStringBuilder);
        builder.sort("timestamp", SortOrder.DESC);
        // 找出历史排序最高的一条
        CollapseBuilder collapseBuilder = new CollapseBuilder("title_keyword");
        InnerHitBuilder innerHitBuilder = new InnerHitBuilder("top_hot");
        innerHitBuilder.setSize(1);
        SortBuilder sortBuilder = SortBuilders.fieldSort("hot_number").order(SortOrder.DESC);
        innerHitBuilder.addSort(sortBuilder);
        collapseBuilder.setInnerHits(innerHitBuilder);
        builder.collapse(collapseBuilder);
        builder.size(30);
        return esUtil.search(type+"_data", builder, SearchData.class);
    }

    @Override
    public List<SearchDetail> searchDetail(String type, int uId) {
        return searchDetailMapper.queryDetail(type, uId);
    }
}

EsUtil

ES实现工具类

@Component
public class EsUtil {
    @Value("${es.host}")
    private String host;
    @Value("${es.port}")
    private int port;
    @Value("${es.scheme}")
    private String scheme;

    private static RestHighLevelClient client = null;

    @PostConstruct
    public void init() {
        try {
            if (client != null) {
                client.close();
            }
            client = new RestHighLevelClient(RestClient.builder(new HttpHost(host, port, scheme)));
        } catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    /**
     * Description: 搜索
     *
     * @param index   index
     * @param builder 查询参数
     * @param c       结果类对象
     * @return java.util.ArrayList
     * @author fanxb
     * @date 2019/7/25 13:46
     */
    public <T> List<T> search(String index, SearchSourceBuilder builder, Class<T> c) {
        SearchRequest request = new SearchRequest(index);
        request.source(builder);
        try {
            SearchResponse response = client.search(request, RequestOptions.DEFAULT);
            SearchHit[] hits = response.getHits().getHits();
            List<T> res = new ArrayList<>(hits.length);
            for (SearchHit hit : hits) {
                res.add(JSON.parseObject(hit.getSourceAsString(), c));
            }
            return res;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

Controller

@Controller
@RequestMapping("/search")
public class searchController {

    private static Logger logger = LoggerFactory.getLogger(IndexController.class);

    @Resource
    SearchService searchService;

    @RequestMapping(value = "/searchTitle", method = RequestMethod.GET)
    public String searchTitle(@RequestParam(value = "title") String title, @RequestParam(value = "type") String type ,ModelMap map){
        UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String name = userDetails.getUsername();
        logger.info("用户名=" + name + "&行为=历史热度查看:" + title + "|" + type);

        map.addAttribute("titleData", title);
        List<String> time = new ArrayList<>();
        List<Integer> hotNumber = new ArrayList<>();
        List<SearchData> hotSpots = searchService.searchByName(title, type);
        for (SearchData hotSpot: hotSpots){
            time.add(hotSpot.getTimestamp().replace('T', ' '));
            hotNumber.add(hotSpot.getHotNumber());
        }
        map.addAttribute("timeData", time);
        map.addAttribute("hotNumberData", hotNumber);
        return "search/searchTitle";
    }

    @RequestMapping(value = "/searchDetail", method = RequestMethod.GET)
    @ResponseBody
    public SearchDetail searchDetail(@RequestParam(value = "uId") int uId, @RequestParam(value = "type") String type ,ModelMap map){
        UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String name = userDetails.getUsername();
        logger.info("用户名=" + name + "&行为=详情查看:" + uId + "|" + type);
        List<SearchDetail> searchDetails = searchService.searchDetail(type, uId);
        return searchDetails.get(0);
    }

    @PostMapping(value = "/searchKeywords")
    public String searchKeywords(@ModelAttribute("searchKeywords") @Valid SearchKeywords searchKeywords, BindingResult result, Model model){
        UserDetails userDetails = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String name = userDetails.getUsername();
        logger.info("用户名=" + name + "&行为=关键词查找:" + searchKeywords.getKeywords() + "|" + searchKeywords.getType() + "|" + searchKeywords.getRelation());

        if (result.hasErrors()){
            return "search/searchKeywords";
        }
        String type = getTypeName(searchKeywords.getType());
        List<SearchData> searchHotSpotData = searchService.searchByKeyword(searchKeywords.getKeywords(), type, searchKeywords.getRelation());
        model.addAttribute("searchHotSpotData", searchHotSpotData);
        model.addAttribute("dataType", type);
        return "search/searchKeywords";
    }

    @GetMapping(value = "/searchKeywords")
    public String toSearchKeywords(Model model){
        model.addAttribute("searchKeywords", new SearchKeywords());
        return "search/searchKeywords";
    }

    private String getTypeName(String type) {
        switch (type){
            case "微博":
                return "weibo";
            case "牛客":
                return "niuke";
            case "虎扑":
                return "hupu";
            case "掘金":
                return "juejin";
            default:
                return "weibo";
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读