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

时间:2014-07-10 23:58:14

标签: c# mongodb mongodb-.net-driver mongodb-query

我正在尝试文本查询集合并以文本匹配顺序检索结果。 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;
    }
}

但我错过了如何投射&#34; textScore&#34;将值计入我的结果中,以便MetaTextScorespecify the column SetSortOrder {。}}。

1 个答案:

答案 0 :(得分:4)

我能够通过反复试验来解决这个问题。诀窍是你的数据对象需要有一个字段,它将保存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]装饰。因此,通过在产生数据对象之前擦除数据对象的值,可以将数据对象保存回集合中而不会产生垃圾值。