【问题标题】:How to update a document to embed an existing document from a different collection in mongoose如何更新文档以在 mongoose 中嵌入来自不同集合的现有文档
【发布时间】:2023-04-01 02:55:01
【问题描述】:

我有两个架构,称为 Fruit 和 Person,它们的集合分别是 fruits 和 people。它们都属于名为 fruitsDB 的数据库。

水果模式:

const fruitSchema = new mongoose.Schema({
  name: String,
  score: Number,
  review: String
});

const Fruit = mongoose.model('Fruit', fruitSchema);

人物架构:

const personSchema = new mongoose.Schema({
  name: String,
  age: Number,
  favouriteFruit: fruitSchema //creating a relationship with the fruitschema
});

const Person = mongoose.model('Person', personSchema);

我已经将一些文档插入到 fruits 集合中,它是这样的:

{ "_id" : ObjectId("5f0ef3efcb6ec717ecda8049"), "name" : "Apple", "score" : 8, "review" : "Pretty solid as a fruit.", "__v" : 0 }
{ "_id" : ObjectId("5f0efa8ee37b6309d8d968fe"), "name" : "Kiwi", "score" : 10, "review" : "The best fruit!", "__v" : 0 }
{ "_id" : ObjectId("5f0efa8ee37b6309d8d968ff"), "name" : "Orange", "score" : 4, "review" : "Too sour for me!", "__v" : 0 }
{ "_id" : ObjectId("5f0efa8ee37b6309d8d96900"), "name" : "Banana", "score" : 7, "review" : "It's nice", "__v" : 0 }
{ "_id" : ObjectId("5f11bc01574df316f4072a46"), "name" : "Pineapple", "score" : 8, "review" : "Great fruit!", "__v" : 0 }

这就是 people 集合的样子:

{
        "_id" : ObjectId("5f11b3e1be240f0c50ca3b26"),
        "name" : "John",
        "age" : 37,
        "__v" : 0
}
{
        "_id" : ObjectId("5f11b62c2ae86609ece9287f"),
        "name" : "Amy",
        "age" : 12,
        "__v" : 0
}

如果“John”有最喜欢的水果,我想在“John”字段的“fruits”集合中嵌入一个“fruit”文档(例如:Kiwi)作为favouriteFruit 字段。像这样:

{
                 "_id" : ObjectId("5f11b3e1be240f0c50ca3b26"),
                "name" : "John",
                 "age" : 37,
       "favouriteFruit": {
                             "_id" : ObjectId("5f0efa8ee37b6309d8d968fe"),
                            "name" : "Kiwi",
                            "score" : 10,
                           "review" : "The best fruit!",
                            "__v" : 0
                         },
                "__v" : 0
}

如何在猫鼬中做到这一点?如何更新“John”文档以嵌入水果集合中的现有文档“Kiwi”?

【问题讨论】:

  • 有人请帮忙!

标签: javascript node.js mongodb mongoose


【解决方案1】:

我认为这个问题有一个解决方法。整个问题可以分为两部分。

  1. 从水果集合中检索所需的水果。
  2. 使用从第一步中检索到的水果文档更新所需的文档。

这两个步骤都可以使用 Mongoose 执行。

Fruit.findOne({name: "Kiwi"}, function(err, fruit) {
    if(err) {
        console.log("Error finding Fruit.");
    }
    else {
        Person.updateOne({name: "John"}, {favouriteFruit: fruit }, function(err) {
            if (err) {
                console.log(err);
            } else {
                mongoose.connection.close();
                console.log("Successfully updated document.");
            }
        });
    }
});

【讨论】:

    【解决方案2】:

    这不是一个答案,但我想理清一个误区,评论框有限。

    favouriteFruit: fruitSchema //creating a relationship with the fruitschema

    以上不是关系,它是使用fruitSchema的子文档。 如果您要将猕猴桃添加为最喜欢的水果,那么它将是一个完全不同的猕猴桃,仅作为子文档存在 在个人文档中。更新 fruits-collection 中的 kiwi-document 不会反映到这个 kiwi。

    虽然它现在可能不是您想要的,但它仍然是 mongodb 最理想的模式,因为您在检索数据时甚至不需要思考。重复数据并不重要。 MongoDb 是非关系型的。

    但是你还是可以通过mongoose populate来获取相关文档:

    // You make the schema like this:
    
    const personSchema = new mongoose.Schema({
      name: String,
      age: Number,
      favFruit: { type: ObjectId, ref: 'Fruit' } // This will store nothing but the object-id
    });
    

    您仍然可以像往常一样保存它

    const kiwi = await Fruit.findOne({ name: "kiwi" }).exec();
    const ben = new Person({ name: "Ben", age: 26 });
    person.favFruit = kiwi;
    await ben.save(); // The schema will filter away everything but the id from favFruit.
    

    但是稍后当你再次检索 Ben 时,你会发现他最喜欢的水果只不过是一个 ObjectID!:

    const ben = await Person.findOne({ name: "Ben" }).exec();
    console.log( ben.favFruit );   // ObjectID("abc123...")
    

    所以现在你需要在你想使用它时填充该字段:

    const ben = await Person.findOne({ name: "Ben" }).populate("favFruit").exec();
    console.log( ben.favFruit ); // { _id: ObjectID("abc123..."), name: "Kiwi", .... }
    

    Mongoose 会进行两个数据库查询来完成这项工作。 (它仍然非常快,但应该注意。)

    【讨论】:

      【解决方案3】:

      我使用{$set : {favouriteFruit: kiwi}}而不是{favouriteFruit: kiwi}来更新文档

      Person.updateOne({name: 'John'}, {$set : {favouriteFruit: kiwi}}, (err)=>{
          if(err){
              console.log(err);
          }
          else{
              console.log("successfully updated");
          }
      });
      

      【讨论】:

        猜你喜欢
        • 2014-06-12
        • 2023-03-10
        • 1970-01-01
        • 2011-12-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-04
        相关资源
        最近更新 更多