Elasticsearch 7.15.2 使用

1、准备工作

Elasticsearch对于JDK、中文词库、spring-data-elasticsearch的版本有要求

中文词库的版本需要和Elasticsearch的版本一模一样,spring-data-elasticsearch的版本需要为4.3.4.

Elasticsearch 7.15.2需要JDK11的环境,如果你的电脑JDK版本是JDK8,则需要使用Elasticsearch自带的JDK。打开bin目录,修改elasticsearch-env.bat文件中选择Java环境的部分如下:

rem comparing to empty string makes this equivalent to bash -v check on env var
rem and allows to effectively force use of the bundled jdk when launching ES
rem by setting JAVA_HOME=
set JAVA="%ES_HOME%\jdk\bin\java.exe"
set JAVA_HOME="%ES_HOME%\jdk"
set JAVA_TYPE=bundled jdk

如果你使用的是windows系统,那么config目录下的elasticsearch.yml中默认的Linux路径设置需要更改为windows格式的:

# ----------------------------------- Paths ------------------------------------
#
# Path to directory where to store the data (separate multiple locations by comma):
#
path.data: D:\EnvironmentNewCoder\data\elasticsearch-7.15.2\data
#
# Path to log files:
#
path.logs: D:\EnvironmentNewCoder\data\elasticsearch-7.15.2\logs

2、配置elasticsearch高级客户端RestHighLevelClient

@Configuration
public class ElasticsearchConfig {
    @Bean
    public RestHighLevelClient restHighLevelClient() {
        ClientConfiguration configuration = ClientConfiguration.builder()
                .connectedTo("127.0.0.1:9200")
                .build();
        RestHighLevelClient client = RestClients.create(configuration).rest();
        return client;
    }
}

3、在想查询的实体类上增加响应的注解

@Data
@NoArgsConstructor
@AllArgsConstructor
@Document(indexName = "discusspost")//indexName:索引名,type:固定_doc,shards:分片,replicas:备份
public class DiscussPost {
    @Id
    private int id;

    @Field(type = FieldType.Integer)
    private int userId;

    //analyzer:互联网校招--->建立最大的索引(就是各种拆分)
    //searchAnalyzer 拆分尽可能少的满足意图的分词器
    @Field(type = FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_smart")
    private String title;

    @Field(type = FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_smart")
    private String content;

    @Field(type = FieldType.Integer)
    //0-普通; 1-置顶;
    private int type;//0-普通; 1-置顶;
    @Field(type = FieldType.Integer)
    private int status;//0-正常; 1-精华; 2-拉黑;
    @Field(type = FieldType.Date)
    private Date createTime;
    @Field(type = FieldType.Integer)
    private int commentCount;
    @Field(type = FieldType.Double)
    private double score;//帖子分数
}

4、创建搜索业务层

由于需要分页显示,我们需要查询该关键词的总行数,并且高亮显示关键词。增加实体类对象和删除实体类对象时需要在Elasticsearch中通过消息队列异步的增加和删除。

@Service
public class ElasticsearchService {
    @Autowired
    private DiscussPostRepository discussPostRepository;
    @Autowired
    private RestHighLevelClient restHighLevelClient;

    //保存
    public void saveDiscussPost(DiscussPost post){
        discussPostRepository.save(post);
    }
    //删除
    public void deleteDiscussPost(int id){
        discussPostRepository.deleteById(id);
    }
    //查询
    public SearchHit[] searchDiscussPost(String keyword, int current, int limit) throws IOException {
        SearchRequest searchRequest=new SearchRequest("discusspost");
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();//构造搜索条件

        //2.查询title\content中含有keyWord的
        sourceBuilder.query(QueryBuilders.multiMatchQuery(keyword,"title"));
        sourceBuilder.query(QueryBuilders.multiMatchQuery(keyword,"content"));

        //3.分页查询
        sourceBuilder.from(current).size(limit);

        //4.按照规则排列
        sourceBuilder.sort(SortBuilders.fieldSort("type").order(SortOrder.DESC));
        sourceBuilder.sort(SortBuilders.fieldSort("score").order(SortOrder.DESC));
        sourceBuilder.sort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC));

        //5.给指定字段加上指定高亮样式
        HighlightBuilder highlightBuilder=new HighlightBuilder();
        highlightBuilder.field("title").preTags("<span style='color:red;'>").postTags("</span>");
        highlightBuilder.field("content").preTags("<span style='color:red;'>").postTags("</span>");
        sourceBuilder.highlighter(highlightBuilder);

        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse=restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        return searchResponse.getHits().getHits();
    }
    //查询总数
    public int searchDiscussPostCount(String keyWord) throws IOException {
        SearchRequest searchRequest=new SearchRequest("discusspost");
        SearchSourceBuilder sourceBuilder=new SearchSourceBuilder();//构造搜索条件

        sourceBuilder.query(QueryBuilders.multiMatchQuery(keyWord,"content","title"));

        sourceBuilder.size(10000);

        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse=restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);

        return searchResponse.getHits().getHits().length;

    }
}

5、搜索业务控制层

调用搜索业务后,Elasticsearch给我们返回的都是JSON字符串我们需要将其再转换回实体类对象,如果前端显示出现问题,我们可以考虑加上防止html转义的操作。

@Controller
public class SearchController implements CommunityConstant {

    @Resource
    private ElasticsearchService elasticsearchService;

    @Resource
    private UserService userService;

    @Resource
    private LikeService likeService;


    @RequestMapping(path = "/search", method = RequestMethod.GET)
    public String search(String keyWord, Page page, Model model) throws IOException {

        // 搜索帖子
        SearchHit[] searchHits =
                elasticsearchService.searchDiscussPost(keyWord, page.getCurrent() - 1, page.getLimit());

        // 聚合数据
        List<Map<String, Object>> discussPosts = new ArrayList<>();

        if (searchHits != null) {
            for (SearchHit hit: searchHits) {
                Map<String, Object> map = new HashMap<>();
                // 帖子
                //防止html转义
                //String postJSON = HtmlUtils.htmlUnescape(hit.getSourceAsString());
                DiscussPost post = JSONObject.parseObject(hit.getSourceAsString(), DiscussPost.class);
                map.put("post", post);
                // 作者
                map.put("user", userService.findUserById(post.getUserId()));
                // 点赞数量
                map.put("likeCount", likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId()));
                discussPosts.add(map);
            }
        }

        model.addAttribute("discussPosts", discussPosts);
        model.addAttribute("keyWord", keyWord);

        // 分页信息
        page.setPath("/search?keyWord=" + keyWord);
        page.setRows(searchHits == null ? 0 : elasticsearchService.searchDiscussPostCount(keyWord));

        return "/site/search";
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值