我是Mongoose的新手,我的模式中有一个数组,它是如下所示的嵌套文档:

const userSchema = new Schema({
    username: String
    friends: [friendsSchema],
});

const friendsSchema = new Schema({
    name: { type: String, unique: true },
});

假设我想将一位朋友添加到特定用户,我需要执行以下操作:

  • 判断用户id是否有效
  • 判断数据库中是否存在该用户ID
  • 如果用户存在,判断他是否已经有一个使用该名字的朋友
  • 如果他不把一个新朋友推入朋友阵营

我最初认为,一旦我获得了用户,我可以简单地在user.Friends数组上执行Foreach循环来验证该朋友的存在.然而,事实证明,mongoose Arrays的行为与常规的JavaScript数组不同.这非常令人沮丧,因为这意味着我需要构造一个复杂的查询,这可能会导致额外的数据库读取,而不是直接访问用户并判断来自User对象的所需信息.因此,我想出了以下实现:

    let { name, userId } = req.body;
    try {
        //check if userId is a valid mongoose objectId
        if (!mongoose.Types.ObjectId.isValid(userId)) {
            res.status(404).json({ error: "invalid user id" });
        }
        // get the user
        let user = await userModel.findById(userId);
        if (!user) {
            res.status(404).json({ error: "user not found" });
        }
        
        let user = user.friends.foreach(friend =>{ 
                   if (friend.name === name)
                      {     
                        res.status(404).json({error: "friend already added to user"});
                      }
        }); 
        
        user.friends.push({ name});
        user.save();
        res.status(200).json(user);
  • 有没有可能在一个查询中完成前面的所有步骤,就像一个数据库读取可以执行所有操作一样?

  • 在Mongoose上有一个不同的数组类型的合理性是什么?

PS:这不是关于如何推送和保存到数组的重复问题

推荐答案

你不需要找到用户,也不需要遍历他们的朋友.如果不满足条件,则只需执行条件更新并将朋友推送到array.例如:

删除此处及之后的所有内容:

let user = await userModel.findById(userId);

更改为:

const user = await userModel.findOneAndUpdate(
   {
      _id: userId, //< Find a user with this id
      'friends.name': { $ne: name } //< But also can't have a friend already with this name 
   },
   {
      $push: { // If you find a user with that id and no existing friend then push
         "friends": {name: name}
      }
   },
   { new: true } //< This tells mongoose to give you back the user with the friend added i.e the updated version
);
if (!user) {
   res.status(404).json({ error: "user not found or friend already added" });
} else{
   res.status(200).json(user);
}

如果您真的想要,您仍然可以首先判断用户是否存在,并快速:

const existingUser = await userModel.findById(userId);

然后根据返回值执行有条件的更新,但是您的应用程序确实不应该允许您的用户try 并更新不存在的用户.

Node.js相关问答推荐

如何使用updateMany()和Node.js的方法?

如何使用聚合管道交换键值对

NPM:无法导入本码模块

try 使用Express和连接池将数据插入MySQL数据库时出现拒绝访问错误

为什么我收到此错误:MissingSchemaError:架构尚未为模型&业务&注册

如果我加入另一个公会且我的​​机器人已在其中,欢迎消息发送错误

尽管 tsconfig 中提供了正确的路径,但仍出现找不到模块错误

Prisma 和 Nextjs:重新部署之前内容不会更新

几个 lambda 共有的函数

在 Nest 项目上运行 Jest 测试时,我的文件无法找到一个在测试之外没有任何问题的模块

如果我在父文件夹中运行,子进程生成不起作用

有没有办法判断 UUID 是否是使用 node.js 中的特定命名空间生成的?

在 `DataFrame` 上使用用户定义的可链接函数抽象出 Polars 表达式

如何让我的 Next.js 应用在运行 ubuntu-latest 的 Azure 应用服务中启动?

如何从 github 编译第三方扩展?

Firestore promise 在退货前等待产品详细信息

在安装 tensorflow 时遇到问题

为什么我在生产环境中 deproy Next.js 示例项目时 CSS 不起作用?

使用 ES6 语法和动态路径导入模块

使用 gzip/deflate 压缩的简单 HTTP 请求