Node js + Mongodb лучший способ выбрать количество c документов - PullRequest
0 голосов
/ 01 августа 2020

Как лучше выбрать количество пользователей?

Будет ли код фильтрации JavaScript работать нормально при увеличении количества пользователей?

  1. Использование нескольких Запросы mongodb

     const db = fastify.mongo.db;
     const users_collection = await db.collection('users');
    
     let users = {
         registered: {
             count: null,
             typed_count: {
                 vk: null,
                 ok: null,
                 google: null,
                 oneclick: null,
             },
         },
     };
    
     users.registered.count = await users_collection.countDocuments();
     users.registered.typed_count.vk = await users_collection.countDocuments({ 'social.vk': { $exists: true } });
     users.registered.typed_count.ok = await users_collection.countDocuments({ 'social.ok': { $exists: true } });
     users.registered.typed_count.google = await users_collection.countDocuments({ 'social.google': { $exists: true } });
     users.registered.typed_count.oneclick = await users_collection.countDocuments({ social: { $exists: false } });
    
  2. Использование одного запроса mongodb и javascript фильтрация

     const db = fastify.mongo.db;
     const users_collection = await db.collection('users');
    
     let users = {
         registered: {
             count: null,
             typed_count: {
                 vk: null,
                 ok: null,
                 google: null,
                 oneclick: null,
             },
         },
     };
    
     const data = await (await users_collection.find()).toArray();
     users.registered.count = data.length;
     users.registered.typed_count.vk = data.filter((obj) => obj.social && obj.social.vk).length;
     users.registered.typed_count.ok = data.filter((obj) => obj.social && obj.social.ok).length;
     users.registered.typed_count.google = data.filter((obj) => obj.social && obj.social.google).length;
     users.registered.typed_count.oneclick = data.filter((obj) => !obj.social).length;
    

1 Ответ

1 голос
/ 02 августа 2020

Первый метод займет больше времени, поскольку задействовано слишком много network requests и

Второй метод займет слишком много вашего server's memory (RAM), так как все документы сначала будут помещены в память.

Таким образом, мы можем сократить как время, так и память, используя MongoDB aggregation's $group конвейер, который будет выглядеть примерно так

db.collection.aggregate([
  {
    $group: {
      _id: null,
      vk: {
        $sum: {
            $cond: [{ $gt: ["$social.vk", null]}, 1, 0]
        }
      },
      ok: {
        $sum: {
          $cond: [{ $gt: ["$social.ok", null]}, 1, 0]
        }
      },
      google: {
        $sum: {
          $cond: [{ $gt: ["$social.google", null]}, 1, 0]
        }
      },
      oneclick: {
        $sum: {
          $cond: [{ $lte: ["$social", null]}, 1, 0]
        }
      },
      
    }
  }
])

Рабочий пример

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...