首页 文章

如何引用和填充嵌套模式?

提问于
浏览
0

TL;DR 如何在同一个集合中引用(并填充)子文档?

我已经尝试了一段时间来填充对Mongoose模式中的子文档的引用 . 我有一个主模式(MainSchema),它包含位置和联系人的数组 . 这些位置引用了这些联系人 .

在我的位置数组中,我通过联系人的_id引用这些联系人 . 见下文 .

import mongoose from 'mongoose';

const LocationSchema = new mongoose.Schema({
  city: {type: String},
  contact: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'Contact' //alternative tried: refPath: 'contacts'
  } 
});
const Location = mongoose.model('Location', LocationSchema);

const ContactSchema = new mongoose.Schema({
  firstName: {type: String},
  lastName: {type: String}
});
const Contact = mongoose.model('Contact', ContactSchema );

const MainSchema = new mongoose.Schema({
  name: {type: String},
  locations: [LocationSchema],
  contacts: [ContactSchema]    
});

export.default mongoose.model('Main', 'MainSchema');

现在,当我想填充位置的联系人时,我得到null或只返回普通的_id字符串 . 下面是我的填充代码 . 我已经尝试了我能找到的每一个组合,包括使嵌套文档成为他们自己的模型,并尝试不同的方式来引用它们 .

MainSchema.statics = {
  get(slug) {
    return this.findOne({name})
      .populate('locations.contact')
      .exec()
      .then((company) => {
        if (company) {
          return company;
        }
        const err = 'generic error message';
        return Promise.reject(err);
      });
    }
  };

我也试过新的方法无济于事:

populate({
  path: 'locations',
  populate: {
    path: 'contacts',
    model: 'Contact'
  }
});

我必须在这里遗漏一些东西 . 但是什么?

编辑了问题以按要求显示完整的查询语句

2 回答

  • 0

    因此,以您的模式为例,我将执行以下操作 . 请注意,我并没有说我的方法是最好的方法,但我有一个与你完全相似的案例 .

    猫鼬模型

    import mongoose from 'mongoose';
    
    const LocationSchema = new mongoose.Schema({
        city: {type: String},
        contact: { type: Schema.Types.ObjectId, ref: 'Contact'}
    });
    
    const ContactSchema = new mongoose.Schema({
        firstName: {type: String},
        lastName: {type: String}
    });
    
    
    const MainSchema = new mongoose.Schema({
        name: {type: String},
        locations: [{ type: Schema.Types.ObjectId, ref: 'Location' }],
    });
    
    const Main = mongoose.model('Main', MainSchema);
    const Location = mongoose.model('Location', LocationSchema);
    const Contact = mongoose.model('Contact', ContactSchema );
    

    注意:在你的主模式中我是've removed the contacts since I understand from your example that each location has it'自己的联系人,所以实际上在 MainSchema 你不需要 ContactSchema

    插入数据的控制器

    这里的想法是你必须将每个文档的引用 _id 传递给另一个文档,下面的例子是模型,请调整它以适合你的 app . 我使用了一个 data 对象,我假设它有一个位置和一个人联系

    async function addData(data) {
    
        //First you create your Main document
        let main = await new Main({
            name: data.name
        }).save();
    
        //Create the contact document in order to have it's _id to pass into the location document
        let contact = await new Contact({
            firstName: data.fistName,
            lastName: data.lastName
        });
    
        //Create the location document with the reference _id from the contact document
        let location = await new Location({
            city: data.city,
            contact: contact._id
        }).save();
    
        //Push the location document in you Main document location array
        main.locations.push(location);
        main.save();
    
        //return what ever you need
        return main;
    }
    

    查询

    let mainObj = await Main.findOne({name})
        .populate({path: 'locations', populate: {path: 'contact'}})
        .exec();
    

    这种方法对我有用,希望它也能为你服务

  • 0

    在搜索了一些之后,我发现一个完全相同的案例在Mongoose github上发布了一个问题issue tracker .

    根据Mongoose的主要维护者,这种形式的填充是不可能的:

    如果嵌入了subdocs,则无法在数组上运行populate(),因为subdocs存储在doc本身而不是单独的集合中 .

相关问题