Node.js使用Mongoose统计用户文档并拼接更新Songlist字段实现问题
实现方案
你原有代码的第一个问题是List.countDocuments({})统计的是整个集合的所有文档数,不是你要的指定用户的对应文档数,逻辑第一步就不符合需求。
推荐使用Mongoose内置的findOneAndUpdate配合upsert参数实现需求,仅需一次数据库请求,是原子操作不会有并发冲突,完全不需要自己写count判断逻辑,代码如下:
const List = require('../Models/list.js'); async function updateUserSonglist(userName, newSong) { await List.findOneAndUpdate( // 查询条件:匹配对应用户的文档 { User: userName }, // 聚合更新逻辑,实现字段自引用拼接 [ { $set: { Songlist: { $concat: [ // 新文档无Songlist时用空字符串兜底,避免拼接null { $ifNull: ["$Songlist", ""] }, // 原有内容不为空时才加分隔符,避免首条内容前多余| { $cond: [{ $ifNull: ["$Songlist", false] }, "|", ""] }, newSong ] } } } ], // upsert=true表示匹配不到文档就自动新建 { upsert: true } ); console.log('done'); } // 调用方法 updateUserSonglist(User.name, args[0]);
如果你一定要沿用你原来的count判断逻辑(不推荐,两次数据库请求,并发场景下可能生成重复文档),修正后的代码如下:
const List = require('../Models/list.js'); const targetUser = User.name; const newSong = args[0]; // 统计指定用户的文档数,不是全集合 List.countDocuments({ User: targetUser }, async (err, count) => { if (err) { console.error(err); return; } if (count > 0) { // 存在文档,执行追加更新 await List.updateOne( { User: targetUser }, [{ $set: { Songlist: { $concat: ["$Songlist", "|", newSong] } } }] ); } else { // 不存在文档,新建 await List.create({ User: targetUser, Songlist: newSong }); } console.log('done'); });
内容的提问来源于stack exchange,提问作者Aqua
相关产品推荐
相关产品推荐

