我尝试使用MongoDB .NET客户端运行聚合管道时遇到问题。我的代码如下所示:
public async Task<IEnumerable<string>> GetPopularTags(int count)
{
var events = _database.GetCollection<Event>(_eventsCollectionName);
var agg = events.Aggregate();
var unwind = agg.Unwind<Event, Event>(e => e.Tags);
var group = unwind.Group(e => e.Tags, v => new { Tag = v.Key, Count = v.Count() });
var sort = group.SortByDescending(e => e.Count);
var project = group.Project(r => r.Tag);
var limit = project.Limit(count);
var result = await limit.SingleOrDefaultAsync();
return result;
}
(每个阶段使用单独的变量只是为了调试)
[尝试获取管道的结果(最后一个变量)时,出现以下错误:
System.InvalidCastException:无法将类型为'MongoDB.Bson.BsonString'的对象转换为类型为'MongoDB.Bson.BsonDocument']
我想念什么?
提前感谢您的帮助!
SOLUTION
我终于弄清楚,我在最后一行收到异常的事实与错误的位置无关。我尝试在每个阶段运行.SingleOrDefault()
以查看输出,并且我注意到我的管道存在两个问题。
我的展开阶段正在尝试返回Event
对象,但是由于它正在展开Tags
属性(它是List<string>
),因此它试图将其设置为string
并抛出异常。我解决了这个问题,方法是将输出类型设置为默认的BsonDocument
,然后在下一阶段使用["Tags"]
访问器获取所需的值。它看起来像这样:
var dbResult = await events.Aggregate()
.Unwind(e => e.Tags)
.Group(e => e["Tags"], v => new { Tag = v.Key, Count = v.Count() })
我的项目阶段由于某种原因无法正常工作。我无法将Tag
属性(原来是BsonValue
类型)转换为string
。最后,我删除了该阶段,并将其替换为dbResult.Select(t => t.Tag.AsString)
以将其转换为字符串。不是最优雅的解决方案,但总比没有好。
最后,我的代码最终看起来像这样:
public async Task<IEnumerable<string>> GetPopularTags(int count)
{
var events = _database.GetCollection<Event>(_eventsCollectionName);
var dbResult = await events.Aggregate()
.Unwind(e => e.Tags)
.Group(e => e["Tags"], v => new { Tag = v.Key, Count = v.Count() })
.SortByDescending(e => e.Count)
.Limit(count)
.ToListAsync();
var result = dbResult.Select(t => t.Tag.AsString);
return result;
}
您面临的问题基本上可以简化为下面的代码行: