以下是我的userproduct模式:

const productSchema = new Schema({
  //... 
  addedBy: {
    type: mongoose.Schema.Types.ObjectId,
    ref: "users"
  }
});

const userSchema = new Schema({   
  //...
  addedItems: [{
    type: mongoose.Schema.ObjectId,
    ref: "products"
  }]
});

mongoose.model("products", productSchema);
mongoose.model("users", userSchema);

在我的 node 后端路由中,我执行以下查询:

User.findOneAndUpdate(
  { _id: req.body.id },
  { $push: { addedItems: newProduct._id } },
  { upsert: true, new: true },
  function(err, doc) {
    console.log(err, doc);
  }
);

console.log号打印出:

{
    //...
    addedItems: [ 5ab0223118599214f4dd7803 ]
}

一切看起来都很好.我会使用mongo db的前端网站查看数据;我用的是mlab.com,这表明:

{
//...
"addedItems": [
        {
            "$oid": "5ab0223118599214f4dd7803"
        },
        {
            "$oid": "5ab0223118599214f4dd7803"
        }
    ]
}

到底发生了什么事?为什么要在addedItems中添加一个附加条目?!即使是我的控制台.日志(log)只显示了一个.

Note:

我测试了后端路由是否被多次调用.事实并非如此.

$push似乎是个问题,因为如果我只有{ addedItems: newProduct._id },那么只有一个条目进入,但它会覆盖整个array.

Edit:

做了一个测试项目来产生同样的结果:https://github.com/philliprognerud/test-mcve-stackoverflow

有人知道发生了什么吗?

推荐答案

这个问题是由您混合使用的promise (通过async/await)和findOneAndUpdate次调用的回调造成的,最终执行了两次命令.

要解决此问题,请执行以下操作:

const updatedUser = await User.findOneAndUpdate(
  { id: userID },
  { $push: { addedItems: newProduct.id } },
  { upsert: true, new: true }
);

console.log(updatedUser);

future 的读者注意到,await的用法在问题中没有显示,而是在MCVE中.

Mongodb相关问答推荐

MongoDB聚合:将文档列表转换为列表

Mongo Aggregate管道-另一个集合中的多个查找

Spring数据MongoDB(聚合)

数组过滤器 MongoDB

如何在 mongodb 查找的外键中使用正则表达式

Mongoose 更新不同类型的记录

Mongodb聚合中基于其他字段值的多个条件的动态新字段值

Mongoose $inc 枚举验证失败

如何在 Mongoose 中定义一个通用的嵌套对象

无法提取地理键,经度/纬度超出范围

你如何让 mongo 在远程服务器上运行?

从命令行创建 MongoDB 用户

.NET 中的 Mongodb 单元测试

在 Mongo 中存储嵌套类别的最有效方法?

使用管道聚合的 Spring Data MongoDB 查找

如何获取 Mongoid 文档的所有字段名称?

mongodb nodejs - 转换圆形 struct

mongoose字符串到 ObjectID

使用 mongodb 在数组中查找子文档

120 个 mongodb 集合与单个集合 - 哪个更有效?