Mongoose Populate 返回 null 或 undefined
Posted
技术标签:
【中文标题】Mongoose Populate 返回 null 或 undefined【英文标题】:Mongoose Populate returning null or undefined 【发布时间】:2013-11-23 21:01:41 【问题描述】:很抱歉,如果这是一个 n00b 问题,我已经搜索 Google 和 Stack 几个小时了,我必须问一下!
我有两个模式,用户和故事,如下所示。我正在尝试使用 Ref 选项为 Story 引用 User 以在查询中填充 - 我之前使用过 mysql,因此想尝试复制 JOIN 语句。 每当我尝试使用填充时,我只会返回 objectID 或 null(如下所示)。
于 11 月 12 日编辑以修复硬编码 ID 并添加控制台数据
story-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');
user-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
);
保存 - 例如 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);
);
登录终端时的示例用户
"__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 查询
我希望发生的事情
是为了能够从故事中获取作者信息——这更像是一个概念证明。 最终我想在 User 模型中引用 Story _id,因为一个用户可以有很多故事,但每个故事只有一个用户,但我想我会先从这里开始。
【问题讨论】:
【参考方案1】:由于您的示例包含原始对象 ID,甚至没有引用为有效的 javascript 字符串,因此很难理解您的问题中的错误与代码中的错误,但大多数情况下,您的第二个查询看起来应该可以工作。我怀疑你混淆了你的 ObjectId 值。您正在为您的故事和您的用户使用相同的 ObjectId,但这是行不通的:
author_id: mongoose.Types.ObjectId(528149b38da5b85003000002),
这与您用于查找故事的 ID 相同。所以我认为解决方法是:
-
确保您在用户集合中有有效的用户记录
确保您的测试故事记录的 story.author_id 与之匹配
确保您是通过故事 ID 而非作者 ID 查找故事。
如果您仍然无法使其正常工作,请将整个内容编码到一个 .js
文件中,其中包含两种模式、两种模型以及一些用于创建记录的代码,然后执行查询并发布。
【讨论】:
您好,我已经更新了示例以不包含硬编码数据 - 这是我努力使事情更清晰(失败)的复制和粘贴错误。尝试仅返回用户 (1) 时,我可以返回有效的用户记录。 author_id 与用户的 _id 匹配,但是即使我尝试将其保存为 ObjectID,它也会在控制台中显示为字符串。会是这样吗? 好的,所以是的,我认为 story.author_id 是 String 而不是 ObjectId 的事实是一个问题。这是一个数据问题,您只需加载并重新保存该记录即可解决。我的猜测是,您在 mongoose 架构完成之前或通过 mongo shell 或其他方式创建了该故事,但本质上数据不符合架构,这始终是此类数据库的风险。 好的,我创建了一个新记录但仍然没有运气,然后我尝试了一个新的 Schema,新的集合以防万一但没有快乐。之后,我将所有内容都放在一个文件中,就像您的第一条评论一样,它与原始/api/query2/:id
等一起工作(!) - 我认为这一定与彼此需要的单独文件有关 - 我找到了这个答案@ 987654321@ 但这在拆分它们时也对我不起作用。所以现在,1个文件!
啊,是的,您可能创建了一个循环需求图,这是节点中的一个禁忌。不要使用require
来相互引用每个模型,只需在架构引用中使用字符串模型名称即可。
就是这样!非常感谢!【参考方案2】:
我被这个问题困扰了一周。在尝试了一切并确保我没有循环引用之后,我决定重置我的数据库。
删除所有集合并再次存储它们后,我由猫鼬的populate()
管理的所有关系都正常工作。
这太令人沮丧了,因为这个问题没有记录在案,而且我浪费了 20 到 30 个小时试图让一个愚蠢的集合参考工作。
【讨论】:
我们现在面临着类似的问题。我们没有对 mongoose 的版本进行任何更改,对于过去 4 年运行良好的一些 populate() 案例仍然返回 null 这里我使用Model.populate()
方法....【参考方案3】:
您是否可能忘记在架构中包含“ref”字段? 我刚刚遇到了这个问题,在我的 Schema 中添加了一个 ref 字段后,它可以立即工作,无需重置数据库。希望这些信息对您有所帮助。
我在这里找到了一个示例:https://mongoosejs.com/docs/3.0.x/docs/populate.html。虽然它是 3.0.x 版的文档,但我发现它甚至对我现在使用的 5.5.5 版也很有帮助。
【讨论】:
经过数小时的调试和挖掘可笑的可怕 Mongoose 文档后,这个答案终于暗示了对 refs 的需求。谢谢狮子座。 FML。【参考方案4】:我偶然发现了这一点,问题在于引用了已删除的文档。如果可以,请重置您的数据库或仔细检查引用的 id
【讨论】:
【参考方案5】:当将 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
);
【讨论】:
你应该包含/要求你想要引用的类,这只是一个例子。不要只是对答案投反对票,并尝试分析示例。【参考方案6】:如果您的数据非常小,请尝试从与填充和主表相关的表中清除您的数据
【讨论】:
【参考方案7】:我在这个问题上停留了 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');
);
);
就是这样,在重新建立与用户的关系后,再次尝试填充该字段。
更新 1: 我忘了提到'ObjectId()'所需的包 必须包括这个
const ObjectId = require('bson');
更新 2: 在深入挖掘之后,我发现更新不是解决方案。我发现您需要包含要填充的所有模型。 例如:有一个连接到用户的 countryModel。然后在您的代码国家模型和用户模型中都应该像这样包含:
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;
【讨论】:
【参考方案8】:首先,当您在创建一些集合后添加填充方法时会发生这种情况。
您可以为连接的模型(全部)提出新请求并创建新集合。那么 populate 方法应该可以工作了。
以前创建的模型仍会发送 null,但新创建的集合应返回填充数据。
【讨论】:
【参考方案9】:当您尝试填充数据库中不再存在的内容时,有时会发生此错误。由于这个原因,我遇到了这个错误。
【讨论】:
以上是关于Mongoose Populate 返回 null 或 undefined的主要内容,如果未能解决你的问题,请参考以下文章
Model.populate() 不是 Mongoose 中的返回文档