首页 > 解决方案 > Node js + Mongodb 更好的方法来选择特定文档的数量

问题描述

选择用户数量的更好方法是什么

如果用户数量增加,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;
    

标签: node.jsmongodboptimizationmongodb-query

解决方案


第一种方法将花费更多时间,因为涉及的人数过多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]
        }
      },
      
    }
  }
])

工作示例


推荐阅读