как дела? :) Хотелось бы совет относительно MongoDB. Краткое объяснение, пожалуйста, пройдите со мной -
Моя коллекция хранит каждый клик в нашей системе, документ кликов выглядит примерно так (упрощенно) -
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string _id { get; set; }
public string VisitorGuid { get; set; }
public int AccountId { get; set; }
Так что _id
- это авто генерируется уникальный идентификатор каждого клика. VisitorGuid
- это сгенерированный гид для каждого уникального клиента (на основе Cook ie), поэтому, если клиент дважды щелкнет ссылку, он создаст 2 документа с разными _id
, но одинаковыми VisitorGuid
.
Мой актуальный вопрос - по этой коллекции я делаю статистику, поэтому, используя приведенный выше пример, я создаю отчет о том, сколько посетителей и сколько кликов было в каждой учетной записи. Чтобы добиться того, чтобы мой запрос состоял из 2 групповых этапов, первый группирует по VisitorGuid
и проецирует новый документ, содержащий количество кликов для указанного c VisitorGuid
, таким образом, в конце я знаю, сколько кликов я иметь в общей сложности (суммируя клики посетителей), а также сколько у меня было посетителей. (IRL я группирую по нескольким полям, а не только по accountId)
Моя проблема в том, что после первой группировки по Mon go невозможно использовать индексы, и этот запрос может занять до нескольких секунд, в зависимости от диапазон дат, который я фильтрую по ... коллекции в настоящее время содержит около 5 миллионов документов, меня больше всего пугает то, что она должна быть способна хранить намного больше, и я не уверен, как она будет обрабатывать такой запрос тогда ...
У кого-нибудь есть предложение? Большое спасибо.
Пример запроса -
// 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());