简体   繁体   English

如何更新文档以在 mongoose 中嵌入来自不同集合的现有文档

[英]How to update a document to embed an existing document from a different collection in mongoose

I have two schemas called Fruit and Person and their collections are fruits and people respectively.我有两个名为FruitPerson的模式,它们的 collections 分别是fruitspeople They both belong in the db called fruitsDB .它们都属于名为fruitsDB的数据库。

Fruit schema:水果模式:

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

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

Person schema:人物模式:

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

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

I have already inserted some docs in to the fruits collection and this is how it looks like:我已经在 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 }

And this is how the people collection looks like:这就是 people 集合的样子:

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

If "John" had a favourite fruit, I want to embed one 'fruit' doc (for eg: Kiwi) from the 'fruits' collection for the "John" field as the favouriteFruit field.如果“约翰”有最喜欢的水果,我想从“约翰”字段的“水果”集合中嵌入一个“水果”文档(例如:猕猴桃)作为最喜欢的favouriteFruit字段。 Like this:像这样:

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

How can I do this in mongoose?我如何在 mongoose 中执行此操作? How can I update the "John" document that way to embed an existing document "Kiwi" from the fruits collection?我如何更新“John”文档以嵌入水果集合中的现有文档“Kiwi”?

I think there is a workaround for this problem.我认为这个问题有一个解决方法。 The whole problem can be broken into 2 parts.整个问题可以分为两部分。

  1. Retrieving the desired fruit from fruits collection.从水果收集中检索所需的水果。
  2. Updating the desired document with the retrieved fruit document from step one.使用从第一步中检索到的水果文档更新所需的文档。

Both the step can be performed using Mongoose.这两个步骤都可以使用 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.");
            }
        });
    }
});

This is not an answer, but I wanted to sort out a misunderstanding and the comment box is limited.这不是答案,但我想解决一个误解,评论框有限。

favouriteFruit: fruitSchema //creating a relationship with the fruitschema

This above is not a relationship, it's a subdocument using the fruitSchema.上面这不是关系,它是使用 fruitSchema 的子文档。 If you were to add kiwi as a favourite fruit, then it would be a completely different kiwi, only existing as a subdocument in the Person-document.如果将奇异果添加为最喜欢的水果,那么它将是完全不同的奇异果,仅作为 Person-document 中的子文档存在。 Updates to the kiwi-document in the fruits-collection would not reflect to this kiwi. fruits-collection 中 kiwi-document 的更新不会反映到这个 kiwi。

While it's probably not what you want right now, it is still very often the most desirable pattern with mongodb, because you don't have to even think when retrieving data.虽然它现在可能不是您想要的,但它仍然是 mongodb 最理想的模式,因为您在检索数据时甚至不必思考。 Duplicate data doesn't matter much.重复数据并不重要。 MongoDb is non-relational. MongoDb 是非关系型的。

But you can still get related documents by using mongoose populate:但是您仍然可以通过使用 mongoose 填充来获取相关文档:

// 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
});

You can still save it as you would normally您仍然可以像往常一样保存它

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.

But later when you retrieve Ben again, you'll find that his fav fruit is nothing but an ObjectID::但是稍后当你再次检索 Ben 时,你会发现他最喜欢的水果不过是一个 ObjectID::

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

So now you need to populate the field when you want to use it:所以现在你需要在你想使用它的时候填充这个字段:

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

Mongoose will make two db-queries to make this work. Mongoose 将进行两次数据库查询以完成这项工作。 (It's still very fast, but one should be aware.) (它仍然非常快,但应该注意。)

I used {$set: {favouriteFruit: kiwi}} instead of {favouriteFruit: kiwi} to update the document我使用{$set: {favouriteFruit: kiwi}}而不是{favouriteFruit: kiwi}来更新文档

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM