使用c#驱动程序从MongoDB Collection上的文本查询中检索相关排序结果

本文关键字:检索 查询 结果 排序 文本 驱动程序 MongoDB Collection 使用 | 更新日期: 2023-09-27 18:12:20

我试图对集合进行文本查询,并按文本匹配顺序检索结果。文档很好地解释了如何在shell中做到这一点:

db.articles.find(
   { status: "A", $text: { $search: "coffee cake" } },
   { score: { $meta: "textScore" } }
).sort( { date: 1, score: { $meta: "textScore" } } )

,但它需要从查找到排序的额外score字段的投影。

在c#中,我有一个像这样的函数:
public IEnumerable<T> TextSearch<T>(MongoCollection<T> coll, string text) {
    var cursor = coll.Find(Query.Text(text))
        .SetSortOrder(SortBy<T>.MetaTextScore(???));
    foreach(var t in cursor) {
        // strip projected score from value
        yield return t;
    }
}

但我错过了如何将"textScore"值投影到我的结果中,以便我可以在SetSortOrder中指定MetaTextScore列。

使用c#驱动程序从MongoDB Collection上的文本查询中检索相关排序结果

我能够通过试验和错误得到这个工作。诀窍在于您的数据对象需要已经有一个保存MetaTextScore值的字段。所以给定接口:

interface ITextSearchSortable {
    double? TextMatchScore { get; set; }
}

最终函数是这样的:

public IEnumerable<T> TextSearch<T>(MongoCollection<T> coll, string text) where T:ITextSearchSortable {
    var cursor = coll.Find(Query.Text(text))
        .SetFields(Fields<T>.MetaTextScore(t => t.TextMatchScore))
        .SetSortOrder(SortBy<T>MetaTextScore(t => t.TextMatchScore));
    foreach(var t in cursor) {
        // prevent saving the value back into the database
        t.TextMatchScore = null;
        yield return t;
    }
}

值得注意的是,TextMatchScore不能有[BsonIgnore]的装饰,否则会有例外。然而,它可以有一个[BsonIgnoreIfNull]装饰。因此,通过在生成数据对象之前清除该值,可以将该数据对象保存回集合中,而无需放入垃圾值。