NodeJS 无法对mongoose执行populate()

zvokhttg  于 2023-11-17  发布在  Node.js
关注(0)|答案(1)|浏览(131)

我是MongoDB和Mongoose的新手,我想在两个文档之间执行populate()。在查阅文档并搜索答案后,我向你寻求帮助。我有两个模型:

票据型号

const mongoose = require('mongoose');

const noteSchema = mongoose.Schema({
    _id: mongoose.Schema.Types.ObjectId,
    title: { 
        type: String, 
        required: true 
    },
    color: { 
        type: String, 
        required: true 
    },
    position: { 
        type: Number, 
        required: true 
    },
    isCheckBoxMode: { 
        type: Boolean,
        required: true 
    },
    items: [{
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Item'
    }]
}, {timestamps: true });

const Note = mongoose.model('Note', noteSchema);

module.exports = Note;

字符串

物料型号

const mongoose = require('mongoose');

const itemSchema = mongoose.Schema({
    _id: mongoose.Schema.Types.ObjectId,
    text: {
        type: String, 
        required: true
    },
    isCompleted: {
        type: Boolean, 
        required: true
    },
    noteId: { 
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Note',
        required: true
    },
}, {timestamps: true });

const Item = mongoose.model('Item', itemSchema);

module.exports = Item;


在这个查询中,我想使用“items”属性检索一个数组,其中包含所有链接到noteId的项目,该属性引用Item文档。正如你在上面看到的,我已经确保在两个文档之间进行引用,一方面使用items属性及其ref Item,另一方面使用NoteId属性,其id对应于正确的note并引用Note文档。
最好有一个例子。我正在使用Mongo Atlas快速部署一个数据库。我用Postman创建了一个note,其id为“6553448ef2c06064f266f785”:
Note document
以及两个项目,每个项目引用noteId“6553448ef2c06064f266f785”:
Item document
不幸的是,当我用populate('items')发送请求来检索我的项目内容时,我收到了一个空数组:

router.get('/:noteId', (req, res, next) => {
    const id = req.params.noteId;
    Note.findById(id)
        .populate('items')
        .exec()
        .then(doc => {
            if (doc) {
                res.status(200).json({
                    notes: doc,
                });
            }else {
                res.status(404).json({message : 'No Valid entry found for provided ID'});
            }
        })
        .catch(err => {
            console.log(err);
            res.status(500).json({error: err});
        });
});


Postman中的请求和响应
request
我找到了另一个解决方案,使用“虚拟”,但它不是最优化的解决方案,我担心会损失性能。

const mongoose = require('mongoose');

const noteSchema = mongoose.Schema({
    _id: mongoose.Schema.Types.ObjectId,
    title: { 
        type: String, 
        required: true 
    },
    color: { 
        type: String, 
        required: true 
    },
    position: { 
        type: Number, 
        required: true 
    },
    isCheckBoxMode: { 
        type: Boolean,
        required: true 
    },
}, {timestamps: true });

noteSchema.virtual('items', {
    ref: 'Item',
    localField: '_id',
    foreignField: 'noteId'
});

noteSchema.set('toObject', { virtuals: true });
noteSchema.set('toJSON', { virtuals: true });

const Note = mongoose.model('Note', noteSchema);

module.exports = Note;


对不起,如果我的问题有点愚蠢,但我找了很长时间,找不到任何解决方案。提前感谢您的帮助
我尝试在Mongoose文档以及其他Stack Overflow帖子之后链接两个文档,但它不起作用。此外,我设置了一个“虚拟”,它可以让我检索所有项目,但这不是优化的。此外,当我使用POST路由添加项目时,如果在我的请求中我还将项目的id添加到note的“items”数组中,填充工作。但这也不是一个优化的解决方案。我想做一个简单的填充之间的两个'参考'。

jgwigjjp

jgwigjjp1#

你的Note模式看起来很好。你有一个items属性,它被正确地定义为一个mongoose.Schema.Types.ObjectId数组,对应的ref:'Note'看起来像教科书一样。
我的建议是显式地将pathmodel属性传递给populate方法,并采用async/await模式,如下所示:

router.get('/:noteId', async (req, res, next) => { //< Mark as async
   try{
      const id = req.params.noteId;
      const doc = await Note.findById(id).populate({ //< use await 
         path: 'items', model: Item //< pass in the path and model
      });
      if(!doc){
         return res.status(400).json({
            message : 'No Valid entry found for provided ID'
         });
      }else{
         return res.status(200).json({
            notes: doc,
         });
      } 
   }catch(err){
      console.log(err);
      res.status(500).json({error: err});
   }
});

字符串

备注:请确保items数组中有ObjectId值。从你的指南针截图中看不清楚,因为items数组在显示中被折叠了。最后,你的指南针是正确的,你不需要虚拟的。

相关问题