0

What would be the better way to select count of users

Will the JavaScript filtering code work fine if the number of users increases?

  1. Using multiple mongodb requests

     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. Using one mongodb request and javascript filtering

     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 Answer 1

1

The First Method will take more time as too many network requests are involved and


The Second Method will take too much of your server's memory (RAM) as all the documents will first be brought into the memory.

So we can reduce both time and memory by using MongoDB aggregation's $group pipeline, which will look something like this

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]
        }
      },
      
    }
  }
])

Working Example

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.