猫鼬填充返回 null 或未定义

luc*_*cca 5 populate mongoose mongodb node.js

如果这是一个 n00b 问题,我很抱歉,我已经在 Google 和 Stack 上搜索了几个小时,我必须问!

我有两个模式,用户和故事,如下所示。我正在尝试使用 Ref 选项在查询中填充来引用用户的故事 - 我之前使用过 mySQL,因此想尝试复制 JOIN 语句。每当我尝试使用 populate 时,我只会返回 objectID 或 null(如下所示)。

11 月 12 日编辑以修复硬编码 ID 并添加控制台数据

故事模式.js

var mongoose = require('mongoose'),
Schema = mongoose.Schema,
User = require('./user-schema');

var StorySchema = new Schema({  
title: { type: String, required: true },  
author_id: { type: Schema.Types.ObjectId, ref: 'User' },
summary: { type: String, required: true },
rating: { type: String, required: true }
});

module.exports = mongoose.model('Story', StorySchema, 'stories');
Run Code Online (Sandbox Code Playgroud)

用户模式.js

var mongoose = require('mongoose'),
Schema = mongoose.Schema;

var UserSchema = new Schema({
    username: { type: String, required: true, index: { unique: true } },
    is_admin: {type: Boolean, required: true, default: false }
});
Run Code Online (Sandbox Code Playgroud)

保存 - 例如 id 硬编码

app.post('/api/new_story', function(req, res){
var story;
story = new Story({
    title: req.body.title,
    author_id: mongoose.Types.ObjectId(req.params._id), 
            /* ex of req.params._id: 527fc8ff241cdb8c09000003*/
    summary: req.body.summary,
    rating: req.body.rating
});

story.save(function(err) {
    if (!err) {
        return console.log("created");
    } else {
        return console.log(err);
    }
});
return res.send(story);
});
Run Code Online (Sandbox Code Playgroud)

登录终端时的示例用户

{
"__v" : 0,
"_id" : ObjectId("527fc8ff241cdb8c09000003"),
"is_admin" : false,
"username" : "ted"
}
Run Code Online (Sandbox Code Playgroud)

登录终端时的示例故事

{
"title" : "Test Story",
"author_id" : "527fc8ff241cdb8c09000003",
"summary" : "Test summary",
"rating" : "12",
"_id" : ObjectId("52827692496c16070b000002"),
"__v" : 0
}
Run Code Online (Sandbox Code Playgroud)

查询

//other mongoose/app includes above
User = require('./config/schema/user-model'),
Story = require('./config/schema/story-model');

// data.author_id = 527fc8ff241cdb8c09000003 
// data.author_id.username = undefined
app.get('/api/query/:id', function (req, res){
return Story.findOne({_id:req.params.id})
.populate( { path: 'User' } )
.exec(function (err, data) {
            console.log(data.author_id);
            console.log(data.author_id.username);
          if (err) {
            return res.json({error:err})
          }
        })
});

// data.author_id = null 
app.get('/api/query2/:id', function (req, res){
return Story.findOne({_id:req.params.id}) //_id hardcoded for example
.populate( 'author_id' )
.exec(function (err, data) {
            console.log(data.author_id);
          if (err) {
            return res.json({error:err})
          }
        })
});
Run Code Online (Sandbox Code Playgroud)

在第一个查询中,我得到了我已经保存的 author_id,这很有意义,因为这就是我保存的 - 但我访问了用户名。

在第二个查询中,我什至无法访问我已经保存的 author_id。

编辑:我可以在没有“填充”的情况下运行正常的 GET 查询

我希望发生什么

是为了能够从故事中访问作者信息——这更像是一种概念证明。最后,我想在 User 模型中引用 Story _id,因为一个用户可以有很多故事,但每个故事只有一个用户,但我想我会先从这里开始。

小智 7

您是否可能忘记在架构中包含“ref”字段?我刚刚遇到这个问题,在将 ref 字段添加到我的架构中后,它会立即工作,无需重置数据库。希望这些信息有帮助。

我发现这里记录了一个示例: https: //mongoosejs.com/docs/3.0.x/docs/populate.html。虽然它是 3.0.x 版本的文档,但我发现它甚至对于我现在正在使用的 5.5.5 版本也很有帮助。


小智 6

我被这个问题困了一个星期。在尝试了一切并确保我没有循环引用之后,我决定重置我的数据库。

删除所有集合并再次存储它们后,我由猫鼬管理的所有关系都populate()有效。

太令人沮丧了,因为这个问题没有记录在案,我浪费了 20-30 个小时试图制作一个愚蠢的收藏参考。

  • 我们现在面临着类似的问题。我们没有对 mongoose 的版本进行任何更改,对于一些过去 4 年工作正常的 populate() 情况仍然返回 null (2认同)

Pet*_*ons 5

由于您的示例包含原始对象 ID,甚至没有被引用为有效的 javascript 字符串,因此很难理解您的问题中的错误与代码中的错误,但大多数情况下,您的第二个查询看起来应该可以工作。我怀疑您混淆了 ObjectId 值。您正在为您的故事和您的用户使用相同的 ObjectId,但这是行不通的:

   author_id: mongoose.Types.ObjectId(528149b38da5b85003000002),
Run Code Online (Sandbox Code Playgroud)

这与您用来查找故事的 ID 相同。所以我认为解决方法是:

  1. 确保您在 users 集合中有一个有效的用户记录
  2. 确保您的测试故事记录的 story.author_id 匹配
  3. 确保您通过故事 ID 而不是 author_id 查找故事。

如果您仍然无法使其正常工作,请在一个.js文件中使用两种模式、两种模型和一些创建记录的代码将整个内容编码,然后进行查询,然后发布。