SpringBoot实现solr多字段模糊查询

本文介绍了如何在Solr中设计数据对象以支持动态内容模糊匹配,包括关键词搜索、数据状态管理和排序规则。同时,展示了如何编写查询代码进行模糊查询并优化排序,确保在处理大量数据(如50万条)时,接口响应速度保持在50ms左右。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

搜索综合/视频需求实现点:

1、搜索关键词:动态内容模糊匹配 或 动态内容标签名称模糊匹配 或 动态关联话题名称模糊匹配
2、数据状态:启用 & 未删除  &  动态展示场景1展示在圈子

3、排序:浏览量 > 点赞量 > 发布时间倒序

为实现当前搜索需求,设计数据对象:

/**
 * @Author: FJT
 * @Date: 2024/1/16 10:27 AM
 */
@Data
public class SaveSolrReq {

    /**话题id**/
    private Long topicId;

    /**话题名称**/
    private String topicName;

    /**话题描述**/
    private String topicDesc;

    /**话题封面图url**/
    private String topicCover;

    /**话题来源 1:官方,2:个人**/
    private String topicSource;

    /**是否是推荐话题:1:是 0:否**/
    private Integer topicRecommend;

    /**话题浏览量**/
    private Long topicPageView;

    /**话题创建时间**/
    private Date topicCreateDateTime;

    /**话题活动id**/
    private Long activityId;

    /**话题分类id**/
    private List<Long> topicCategoryId;

    /**话题分类名称**/
    private List<String> topicCategoryName;

    /**动态id**/
    private Long id;

    /**动态内容**/
    private String momentsContent;

    /**动态video类型 1:图片 2:视频**/
    private Integer videoType;

    /**动态点赞量**/
    private Long momentsLikeNum;

    /**动态浏览量**/
    private Long momentsViewNum;

    /**动态评论量**/
    private Long momentsReviewNum;

    /**动态收藏量**/
    private Long momentsCollectNum;

    /**video地址**/
    private List<String> videoUrls;

    /**图片尺寸 长(px)**/
    private Integer videoLongPx;

    /**图片尺寸 宽(px)**/
    private Integer videoWidePx;

    /**动态创建人用户id**/
    private Long momentsUserId;

    /**动态创建人用户昵称**/
    private String momentsUserName;

    /**动态创建人用户头像**/
    private String momentsUserAvatar;

    /**动态分类id**/
    private List<Long> momentsCategoryId;

    /**动态分类名称**/
    private List<String> momentsCategoryName;

    /**是否是推荐动态 1:是,0:否**/
    private Integer momentsRecommend;

    /**是否开启永久置顶 1:是 0:否***/
    private Integer foreverTop;

    /**发布动态位置**/
    private String location;

    /**发布动态经度**/
    private String longitude;

    /**发布动态纬度**/
    private String latitude;

    /**动态发布时间**/
    private Date momentsCreateDateTime;

    /**动态商品id**/
    private List<Long> momentsProductId;

    /**动态社群id**/
    private List<Long> momentsCommunityIds;

    /**动态展示场景 1:展示在圈子,2:宠物详情开箱精选,3:用品订单开箱精选,4:展示在关注,搜索场景查询1**/
    private Integer momentsShowType;

    /**圈子id 默认为0**/
    private Long communityId;

    /**是否是官方用户 1:是 0:否**/
    private Integer officialUser;

    /**是否删除 1:是 0:否**/
    private Integer deleted;

    /**
     * 是否启用:1-启用,0-禁用
     */
    private Integer enabled;

    /**记录更新时间,系统使用,不用传递**/
    private Date updateDateTime;

}

solr中的schema配置文件,调整字段类型,一般在managed-schema中

注意改完需要重启solr,如果是docker安装的solr的话,直接运行

# 重启solr

docker restart solr 

插入数据验证:

@Override
    public Result saveSolrData(List<SaveSolrReq> reqs) {
        try {
            long l1 = System.currentTimeMillis();
            for (int i = 0; i < reqs.size(); i++) {
                log.info("solr保存数据入参:{}",JSONUtil.toJsonStr(reqs.get(i)));
                    reqs.get(i).setUpdateDateTime(new Date());
                SolrInputDocument inputDocument = new SolrInputDocument();
                Map<String, Object> map = BeanUtil.beanToMap(reqs.get(i));
                if (CollectionUtil.isNotEmpty(map)) {
                    map.forEach((k, v) -> {
                        inputDocument.addField(k, v);
                    });
                }
                solrClient.add(inputDocument);
                if ((i + 1) % 1000 == 0 || i ==  reqs.size() - 1) {
                    log.info("开始提交");
                    solrClient.commit();
                }
            }
            long l2 = System.currentTimeMillis();
            log.info("数据插入耗时:{}",(l2-l1));
            return Result.success();
        } catch (SolrServerException e) {
            log.error("solr数据添加失败:{}", e);
            throw new BusinessException("solr数据添加失败");
        } catch (IOException e) {
            log.error("solr数据添加失败:{}", e);
            throw new BusinessException("solr数据添加失败");
        }
    }

 造50w测试数据:

编写数据查询代码,模糊查询匹配:关键字前后拼*,and条件通过增加fq设置,排序可以根据加入的顺序来控制

public Result<CommunitySearchVo> searchKey(CommunitySearchParam param) {
        //2.创建查询语句
        String keyWord="*"+param.getSearchWord()+"*";
        SolrQuery query = new SolrQuery("momentsContent:"+keyWord+" or momentsCategoryName:"+keyWord+
                " or topicName:"+keyWord);
        query.add("fq", "momentsShowType:" + MomentsShowTypeEnum.TYPE_1.getType());
        query.add("fq", "deleted:0");
        query.add("fq", "enabled:1");
        //增加视频过滤条件
        if (Objects.equals(SearchType.TYPE_2.getType(), param.getSearchType())) {
            query.add("fq", "videoType:"+ SearchType.TYPE_2.getType());
        }
        query.setStart((param.getPage_number() - 1) * param.getPage_size());
        query.setRows(param.getPage_size());
        query.addSort("officialUser", SolrQuery.ORDER.desc);
        query.addSort("foreverTop", SolrQuery.ORDER.desc);
        query.addSort("momentsRecommend", SolrQuery.ORDER.desc);
        query.addSort("momentsViewNum", SolrQuery.ORDER.desc);
        query.addSort("momentsLikeNum", SolrQuery.ORDER.desc);
        query.addSort("momentsCreateDateTime", SolrQuery.ORDER.desc);
        QueryResponse queryResponse = null;
        try {
            //执行查询
            log.info("查询条件:{}",JSONUtil.toJsonStr(query));
            queryResponse = solrClient.query(query);
        } catch (SolrServerException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //5.取文档列表(public class SolrDocumentList extends ArrayList<SolrDocument>)
        List<CommunitySearchVo> list = new ArrayList<>();
        SolrDocumentList documentList = queryResponse.getResults();
        for (SolrDocument solrDocument : documentList) {
            CommunitySearchVo communitySearchVo = BeanUtil.toBean(solrDocument, CommunitySearchVo.class);
            list.add(communitySearchVo);
        }
        return Result.success(list, documentList.getNumFound());
    }

 最终结果实现:按照预期的排序效果进行排序,且按照正常的关键字进行字段模糊搜索,50w接口相应速度也还可以在50ms左右,没有模拟高并发的情况。目前来讲,以当前的业务量足以支撑了,扛不住了再换成solr集群吧

如果有收获请点个赞吧 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值