Как обрабатывать большие скопления коллекций после группировки? - PullRequest
1 голос
/ 23 апреля 2020

как дела? :) Хотелось бы совет относительно 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());

1 Ответ

0 голосов
/ 23 апреля 2020

Индексы применяются, когда данные известны раньше времени запроса (индексы должны быть построены из данных). Когда данные создаются в запросе агрегации, они не будут использовать индексы в смысле слова «индекс коллекции». Тем не менее, определенные операции в памяти могут в принципе использовать алгоритмы, такие как ha sh join (я не знаю, как конкретно это относится к MongoDB), которые можно рассматривать как другое понимание "индекса Msgstr ".

С конвейером агрегации идея, которую я бы сказал в общем, заключается в том, чтобы как можно больше передавать данные с одного этапа на другой. Так что в какой-то момент вам может потребоваться скорректировать ваши запросы, чтобы обеспечить потоковую передачу.

Вы можете проверить производительность или больший набор данных, просто создав такой большой набор данных.

...