MongoDB: динамический счет - PullRequest
       12

MongoDB: динамический счет

1 голос
/ 04 апреля 2019

У меня есть две коллекции. Коллекция 'пользователей' и коллекция 'событий'. В коллекции событий есть первичный ключ, который указывает, какому пользователю принадлежит событие.

Я бы хотел посчитать, сколько событий у пользователя соответствует определенному условию.

В настоящее время я выполняю это как:


db.users.find({ usersMatchingACondition }).forEach(user => {

  const eventCount = db.events.find({
    title: 'An event title that I want to find',
    userId: user._id
  }).count();

  print(`This user has ${eventCount} events`);

});

В идеале я хотел бы получить массив или объект с идентификатором пользователя и количеством событий, которые имеет этот пользователь.

С 10 000 пользователей - это, очевидно, производит 10 000 запросов, и я думаю, что это можно сделать намного эффективнее!

Я предполагаю, что это легко с каким-то агрегированным запросом - но я не знаком с синтаксисом и изо всех сил пытаюсь обернуть его вокруг.

Любая помощь будет принята с благодарностью!

Ответы [ 2 ]

2 голосов
/ 04 апреля 2019

Вам нужно $ lookup , чтобы получить данные из events, соответствующие user_id. Затем вы можете использовать $ filter , чтобы применить условие уровня события и получить счетчик, вы можете использовать $ size operator

db.users.aggregate([
    {
        $match: { //users matching condition }
    },
    {
        $lookup:
        {
            from: 'events',
            localField: '_id', //your "primary key"
            foreignField: 'user_id',
            as: 'user_events'
        }
    },
    {
        $addFields: {
            user_events: {
                $filter: {
                    input: "$user_events",
                    cond: {
                        $eq: [
                            '$$this.title', 'An event title that I want to find'
                        ]
                    }
                }
            }
        }
    },
    {
        $project: {
            _id: 1,
            // other fields you want to retrieve: 1,
            totalEvents: { $size: "$user_events" }
        }
    }
])
0 голосов
/ 04 апреля 2019

Не так много оптимизаций, которые можно выполнить без агрегата, но, поскольку вы специально сказали, что

Сначала вместо

const eventCount = db.events.find({
    title: 'An event title that I want to find',
    userId: user._id
  }).count();

Делайте

const eventCount = db.events.count({
    title: 'An event title that I want to find',
    userId: user._id
  });

Это значительно ускорит ваши запросы, потому что запрос поиска фактически сначала выбирает документы, а затем выполняет подсчет.

Для возврата массива вы можете просто инициализировать массив в начале и нажать {userid: id, count:eventCount} возражает против этого.

...