【发布时间】:2020-04-23 10:03:01
【问题描述】:
我的集合存储了我们系统中的每次点击,点击文档看起来像(简化)-
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string _id { get; set; }
public string VisitorGuid { get; set; }
public int AccountId { get; set; }
所以_id 是每次点击自动生成的唯一标识符。
VisitorGuid 是为每个唯一客户(基于 Cookie)生成的 guid,因此如果客户单击链接两次,它将创建两个具有不同 _id 但相同 VisitorGuid 的文档。
我的实际问题 -
在这个集合上,我正在做统计,所以使用上面的例子,我生成了一个关于每个帐户有多少访问者和多少点击的报告。
为了实现我的查询有 2 个组阶段,第一个由 VisitorGuid 分组,并投影一个新文档,其中包含特定 VisitorGuid 的点击量,这样最后我知道我总共有多少点击(总结访问者的点击次数)以及我有多少访问者。 (IRL 我按多个字段分组,不仅是 accountId)
我的问题是,在第一次分组后 Mongo 无法使用索引,并且该查询可能需要几秒钟,具体取决于我过滤的日期范围。该集合目前拥有大约 500 万个文档,最让我害怕的是它需要能够容纳更多,我不确定它将如何处理这样的查询。
查询示例:
// Use the dates to create ObjectId type for comparison
var startId = new ObjectId(request.FromDate.UtcDateTime, 0, 0, 0).ToString();
var endId = new ObjectId(request.ToDate.UtcDateTime, 0, 0, 0).ToString();
//filter
var builder = Builders<Click>.Filter;
var clickFilters = builder.Gte(c => c._id, startId)
& builder.Lte(c => c._id, endId);
var aggregateOptions = new AggregateOptions { AllowDiskUse = true };
//aggregate clicks -
var clicksAggregationTask = Task.Run(() => collection.Aggregate(aggregateOptions)
.Match(clickFilters)
//group into visitors
.Group(c => c.VisitorGuid, g => new Result()
{
AccountId = g.First().AccountId,
ClickCount = g.Count()
})
//statistics
.Group(
c => new GroupByResult()
{
AccountId = c.AccountId,
},
g => new Res()
{
AccountId = g.First().AccountId,
ClickCount = g.Sum(group => group.ClickCount),
VisitorCount = g.Count()
})
.ToListAsync());
【问题讨论】:
标签: mongodb .net-core nosql bigdata