将MongoDB与C#和驱动程序2.0一起使用,我正在尝试执行以下操作:
这是类的简化版本:
onCreateOptionMenu()
如果我进行文本搜索,则非常简单:
class BigClass
{
[BsonIgnoreIfDefault]
public ObjectId _id { get; set; }
public string Guid { get; set; }
public string Title { get; set; }
public DateTime CreationTime { get; set; }
// lots of other stuff
[BsonIgnoreIfNull]
public double? TextMatchScore { get; set; } // Temporary place for the text match score, for sorting
}
class SmallClass
{
[BsonIgnoreIfDefault]
public ObjectId _id { get; set; }
public string Title { get; set; }
[BsonIgnoreIfNull]
public double? TextMatchScore { get; set; } // Temporary place for the text match score, for sorting
}
如果我想按文字搜索的分数进行排序,那就更麻烦了(并且记录很少):
var F = Builders<BigClass>.Filter.Text("text I am looking for");
var Result = MongoDriver.Find(F).ToListAsync().Result;
基本上它需要我在类中添加一个字段(TextMatchScore)来保存结果。
如果我想获取数据,而不进行排序并将其投影到SmallClass,则很简单:
var F = Builders<BigClass>.Filter.Text("text I am looking for");
var P = Builders<BigClass>.Projection.MetaTextScore("TextMatchScore");
var S = Builders<BigClass>.Sort.MetaTextScore("TextMatchScore");
var Result = MongoDriver.Find(F).Project<BigClass>.Sort(S).ToListAsync().Result;
现在,如果&#34;我想要所有&#34;,那就是问题出现的地方:
var F = Builders<BigClass>.Filter.Text("text I am looking for");
var P = Builders<BigClass>.Projection.Include(_ => _.id).Include(_ => _.Title);
var Result = MongoDriver.Find(F).Project<SmallClass>(P).ToListAsync().Result;
我得到一个例外:
var F = Builders<BigClass>.Filter.Text("text I am looking for");
var P = Builders<BigClass>.Projection.MetaTextScore("TextMatchScore").Include(_ => _.id).Include(_ => _.Title).Include(_ => _.TextMatchScore);
var S = Builders<BigClass>.Sort.MetaTextScore("TextMatchScore");
var Result = MongoDriver.Find(F).Project<SmallClass>.Sort(S).ToListAsync().Result;
正如预期的那样,错误没有在任何地方记录,因为Mongo人希望用户自我记录所有内容。
如果我将投影投向&#39; BigClass&#39;,则没有问题,代码会运行并填充正确的字段。
如果你用C#谷歌那个文字,你找到的帖子是我的,当我试图弄清楚文本搜索时,这也很难记录。
因此,当我们将投影,文本搜索和排序结合起来时,在任何地方似乎都没有任何示例,我只是无法让它工作。
有谁知道这个问题的原因?
答案 0 :(得分:1)
这对我有用:
var client = new MongoClient();
var db = client.GetDatabase("test");
var col = db.GetCollection<BigClass>("big");
await db.DropCollectionAsync(col.CollectionNamespace.CollectionName);
await col.Indexes.CreateOneAsync(Builders<BigClass>.IndexKeys.Text(x => x.Title));
await col.InsertManyAsync(new[]
{
new BigClass { Title = "One Jumped Over The Moon" },
new BigClass { Title = "Two went Jumping Over The Sun" }
});
var filter = Builders<BigClass>.Filter.Text("Jump Over");
// don't need to Include(x => x.TextMatchScore) because it's already been included with MetaTextScore.
var projection = Builders<BigClass>.Projection.MetaTextScore("TextMatchScore").Include(x => x._id).Include(x => x.Title);
var sort = Builders<BigClass>.Sort.MetaTextScore("TextMatchScore");
var result = await col.Find(filter).Project<SmallClass>(projection).Sort(sort).ToListAsync();
我删除了TextMatchScore的包含。它仍然会回来,因为它包含在MetaTextScore中(&#34; TextMatchScore&#34;)。
文档正在进行中。我们首先处理主要用例,因为那些用户受到的影响最大。这个用例并不常见,也没有记录。我们当然接受拉取请求,包括代码和文档。另外,请随时在CSHARP项目下的jira.mongodb.org上提交文档票据。
答案 1 :(得分:0)
适用于 MongoDB.Driver 2.x 的解决方案如下。重要的是不要在投影中包含,因为它会删除默认的,(或记得添加适当的投影)
查询:
{
"find":"SoceCollection",
"filter":{
"$text":{
"$search":"some text to search"
}
},
"sort":{
"TextScore":{
"$meta":"textScore"
}
},
"projection":{
"TextScore":{
"$meta":"textScore"
},
"_id":0,
"CreatedDate":0
},
"limit":20,
"collation":{
"locale":"en",
"strength":1
} ...
代码
var sort = Builders<BigModel>.Sort.MetaTextScore(nameof(LightModel.TextScore));
var projection = Builders<BigModel>.Projection
.MetaTextScore(nameof(LightModel.TextScore))
.Exclude(x => x.Id)
.Exclude(x => x.CreatedDate);
return await Collection()
.Find(filter, new FindOptions { Collation = new Collation("en", strength: CollationStrength.Primary) })
.Project<LightModel>(projection)
.Sort(sort)
.Limit(20)
.ToListAsync();