You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用MongoRepository按分数对搜索结果排序?

可以通过MongoRepository实现按搜索分数排序,核心是利用MongoDB的文本索引结合聚合查询来实现,以下是具体实现思路:

一、先配置文本索引

要让MongoDB计算搜索匹配分数,首先需要给你要搜索的字段(title、index、mainCategory、subCategory)添加文本索引。修改实体类,给目标字段加上@TextIndexed注解:

@Data
@Document(collection = "cad")
public class Cad {
    @Id
    private String id;
    private String author;
    @TextIndexed // 给需要搜索的字段加文本索引
    private String mainCategory;
    @TextIndexed
    private String subCategory;
    @TextIndexed
    private String title;
    @TextIndexed
    private String index;
    private String s3Url;
    private String createdAt;

    // 构造方法保持不变
}

添加注解后,Spring Data MongoDB会自动在MongoDB中创建对应的文本索引。

二、通过@Aggregate注解实现带分数排序的查询

你之前尝试@Aggregate未成功,大概率是聚合管道写法有误。以下是正确的配置,直接在CadRepository中定义方法:

public interface CadRepository extends MongoRepository<Cad, String> {
    // 按搜索文本匹配,返回按分数降序排列的结果
    @Aggregation(pipeline = {
        // 第一步:匹配包含搜索文本的文档
        "{ '$match': { '$text': { '$search': ?0 } } }",
        // 第二步:直接按文本匹配分数降序排序
        "{ '$sort': { 'score': { '$meta': 'textScore' } } }"
    })
    List<Cad> findAllBySearchTextSorted(String searchText);
}

这个聚合管道的逻辑:

  1. $match阶段:使用MongoDB的$text查询匹配搜索文本,仅配置了文本索引的字段会参与匹配
  2. $sort阶段:利用$meta('textScore')直接获取匹配分数,按分数从高到低排序

如果需要把匹配分数返回给前端,可以创建包含分数的DTO类,调整聚合管道添加分数字段:

// 创建DTO类,继承Cad并新增score字段
@Data
public class CadWithScore extends Cad {
    private Double score;
}

// 在Repository中修改方法
@Aggregation(pipeline = {
    "{ '$match': { '$text': { '$search': ?0 } } }",
    "{ '$addFields': { 'score': { '$meta': 'textScore' } } }", // 添加分数字段
    "{ '$sort': { 'score': -1 } }"
})
List<CadWithScore> findAllBySearchTextWithScore(String searchText);

三、修改Service层调用

替换原来的查询方法为新的排序方法即可:

@RequiredArgsConstructor
@Service
public class CadService {
    private final CadRepository cadRepository;

    public List<Cad> searchCadFile(String searchText) {
        try {
            // 调用带排序的查询方法
            return cadRepository.findAllBySearchTextSorted(searchText);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return Collections.emptyList(); // 建议返回空列表而非null,避免空指针
    }
}

为什么原来的方法无法按分数排序?

你之前用的findAllByTitleOrIndexOrMainCategoryOrSubCategoryContains是基于多字段的模糊匹配(本质是$or+$regex查询),这种查询方式MongoDB不会计算匹配分数,自然无法按分数排序。只有使用文本索引+$text查询,才能获得MongoDB生成的匹配分数,进而实现按分数排序。

内容的提问来源于stack exchange,提问作者Yeon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 15:21:02