如何用Mongoose查询获取字符串数组格式的IP列表(非对象数组)
问题
我定义了如下Mongoose Schema:
const proxyIpSchema = new Schema<IProxyIp>({ ip: { type: String, required: true, //ignore duplicate ip unique: true, }, port: { type: Number, required: false, default: null }, reason: { type: String, required: true, default: 'Unknown Detection.' } }, { timestamps: true, } );
我希望查询所有IP属性,得到纯字符串数组格式(如[IP,IP,IP,IP]),而非[{ip: IP}]这样的对象数组。由于map函数会消耗后端算力,我不想使用这种方式。当前我通过以下代码从MongoDB获取IP并存入Redis,但希望优化:
//get all ips from mongo db and push to redis await ProxyIp.find({}, { ip: 1 }).then(async (docs) => { docs.map(async (doc) => { await this.RedisClient?.sAdd(redisTable, doc.ip); }); }).catch((err) => { });
优化方案
1. 直接用MongoDB的distinct获取纯IP数组
因为你的ip字段已经设置了unique: true,使用distinct方法可以直接从数据库层面返回去重后的纯IP字符串数组,完全避免后端处理对象数组的开销:
const ipList = await ProxyIp.distinct('ip');
这行代码直接得到[ip1, ip2, ip3...]格式的结果,无需任何额外转换。
2. 批量写入Redis,减少网络IO
原来的循环调用sAdd会发起多次Redis请求,换成批量写入,一次请求完成所有IP的添加,大幅降低网络开销:
try { const ipList = await ProxyIp.distinct('ip'); if (ipList.length > 0 && this.RedisClient) { // 展开数组批量写入 await this.RedisClient.sAdd(redisTable, ...ipList); } } catch (err) { console.error('同步IP到Redis失败:', err); }
3. 替代方案:用聚合操作生成数组(适合需要额外过滤场景)
如果后续需要对IP做过滤、筛选后再生成数组,可以用MongoDB聚合在数据库层面完成处理,返回纯数组:
const result = await ProxyIp.aggregate([ // 可在这里添加$match做条件过滤 { $group: { _id: null, ips: { $push: "$ip" } } }, { $project: { _id: 0 } } ]); const ipList = result[0]?.ips || []; // 后续批量写入Redis逻辑同上
内容的提问来源于stack exchange,提问作者Rumira Daksith
相关产品推荐
相关产品推荐

