我正在尝试文本查询集合并以文本匹配顺序检索结果。 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;将值计入我的结果中,以便MetaTextScore
中specify the column SetSortOrder
{。}}。
答案 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]
装饰。因此,通过在产生数据对象之前擦除数据对象的值,可以将数据对象保存回集合中而不会产生垃圾值。