Skip to main content
 首页 » 编程设计

c#之使用 C# 驱动程序从 MongoDB 集合的文本查询中检索相关有序结果

2024年02月06日38xing901022

我正在尝试对集合进行文本查询并以文本匹配顺序检索结果。 The docs很好地解释了如何在 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”值投影到我的结果中,这样我就可以 specify the column到 SetSortOrder 中的 MetaTextScore。

请您参考如下方法:

我能够通过反复试验使它正常工作。诀窍是您的数据对象需要已经有一个字段来保存 MetaTextScore 值。所以给定接口(interface):

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] 装饰。因此,通过在生成数据对象之前清除数据对象中的值,可以将数据对象保存回集合中,而无需放入垃圾值。