Mongoose Populate返回null或undefined

时间:2013-11-11 22:05:31

标签: node.js mongodb mongoose populate

如果这是一个n00b问题,我很抱歉,我一直在搜索Google&现在堆叠好几个小时,我得问一下!

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

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

故事schema.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');

用户-schema.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 }
});

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

登录终端时的示例用户<​​/ strong>

{
"__v" : 0,
"_id" : ObjectId("527fc8ff241cdb8c09000003"),
"is_admin" : false,
"username" : "ted"
}

登录终端时的示例故事

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

查询

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

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

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

编辑:我可以正常运行GET查询而不使用'populate'

我想发生什么

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

8 个答案:

答案 0 :(得分:3)

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

   author_id: mongoose.Types.ObjectId(528149b38da5b85003000002),

这与您用于查找故事的ID相同。所以我认为修复是:

  1. 确保用户集合中有有效的用户记录
  2. 确保您的测试故事记录的story.author_id与
  3. 匹配
  4. 确保您按故事ID而不是author_id查找故事。
  5. 如果仍然无法使其正常工作,请在单个.js文件中使用模式,模型和一些代码编写整个内容,以创建记录然后执行查询,然后发布。< / p>

答案 1 :(得分:0)

这个问题困扰了我一周。在尝试了所有内容并确保没有循环引用之后,我决定重设数据库。

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

这太令人沮丧了,因为没有记录此问题,我花了20到30个小时试图制作一个愚蠢的收藏参考书。

答案 2 :(得分:0)

是否有可能忘记在模式中包含“ ref”字段? 我刚遇到此问题,将ref字段添加到Schema后,它可以立即工作,而无需重置数据库。希望这些信息对您有所帮助。

我找到了一个此处记录的示例:https://mongoosejs.com/docs/3.0.x/docs/populate.html。尽管它是3.0.x版本的文档,但我发现即使对于现在正在使用的5.5.5版本,它也很有帮助。

答案 3 :(得分:0)

我偶然发现了这个问题,问题是引用了已删除的文档。如果可以,请重置数据库,或者再次检查引用的ID

答案 4 :(得分:0)

如果您的数据非常小,请尝试从与填充和主数据相关的表中清除数据

答案 5 :(得分:0)

我在这个问题上坚持了 5-6 个小时,并找到了一个非常简单的解决方案。在这种情况下,您可以在这里看到:

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

在 author_id 值 '527fc8ff241cdb8c09000003' 基本上是一个“字符串”而不是 ObjectId。当您从 json 或 csv 还原数据库并且在此过程中 ObjectId 转换为字符串时,就会发生这种情况。在我的情况下,我使用 Python 转储数据并尝试使用 express 检索数据。 所以为了解决这个问题,我简单地使用 express 更新了数据,现在“填充”正在工作 尝试更新数据:

 const { ObjectId }  = require('bson');
    app.get('/update-data', (req,res)=>{
         Story.find()
        .exec((err,posts)=>{
            for(let value of posts)
            {
             User.findOne({ _id : value.author_id })
             exec((err,userData)=>{
                      Story.update({ _id : value._id }, {  author_id : ObjectId(userData._id) })
              .exec((error, resData)=>{
                   console.log(resData);
                 });
               })
            
            }
            res.send('Data Updated, try populating data again');
        });
    });
    

就是这样,在与用户重新建立关系后,再次尝试填充该字段。

更新一:
我忘了提及“ObjectId()”所需的包 必须包括这个

const { ObjectId }  = require('bson');

更新2: 在深入挖掘之后,我发现更新不是解决方案。我发现您需要包含要填充的所有模型。 例如:有一个连接到用户的国家模型。然后在您的代码国家模型和用户模型中都应该像这样包含:

var userModel = require('../<path to model>/userModel');
var countryModel = require('../<path to model>/countryModel');

但是您没有使用 countryModel 但这需要启动。对于国家/地区,型号代码应为: countryModel.js

const mongoose = require('mongoose');

const countrySchema = mongoose.Schema({
country_name : String,
flag_image : String,
country_code : String
});

//user model 
var countryModel = mongoose.model('countries', countrySchema);
module.exports = countryModel;

答案 6 :(得分:0)

首先,当您在创建一些集合后添加 populate 方法时会发生这种情况。

您可以为连接的模型(全部)发出新请求并创建新集合。然后 populate 方法应该可以工作。

之前创建的模型仍然会发送 null,但新创建的集合应该返回填充的数据。

答案 7 :(得分:-1)

当将ref声明为模型类引用而不是模型名称的字符串时,我设法解决了这个问题。

// before
let Schema = mongoose.Schema({
    name: String,
    author: { type: Schema.Types.ObjectId, ref: 'Author' }
});

//after
let Schema = mongoose.Schema({
    name: String,
    author: { type: Schema.Types.ObjectId, ref: Author }
});