[英]Mongoose Populate returning null or undefined
很抱歉,如果这是一个 n00b 问题,我已经在 Google 和 Stack 上搜索了几个小时,我不得不问!
我有两个模式,用户和故事,如下所示。 我正在尝试使用 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');
用户模式.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 查询
我想发生什么
是为了能够从故事中访问作者信息——这更像是一个概念证明。 最后,我想引用用户 model 中的故事 _id,因为一个用户可以有很多故事,但每个故事只有一个用户,但我想我会先从这里开始。
我被这个问题困了一个星期。 在尝试了一切并确保我没有循环引用之后,我决定重置我的数据库。
删除所有集合并再次存储它们后,我所有由猫鼬的populate()
管理的关系都起作用了。
太令人沮丧了,因为这个问题没有记录在案,我浪费了 20-30 个小时试图制作一个愚蠢的收藏参考。
由于您的示例包含原始对象 ID,甚至未被引用为有效的 javascript 字符串,因此很难理解您的问题与代码中的错误是什么,但大多数情况下,您的第二个查询看起来应该可以工作。 我怀疑您混淆了 ObjectId 值。 您正在为您的故事和您的用户使用相同的 ObjectId,但这是行不通的:
author_id: mongoose.Types.ObjectId(528149b38da5b85003000002),
这与您用来查找故事的 ID 相同。 所以我认为解决方法是:
如果您仍然无法使其正常工作,请在单个.js
文件中使用两种模式、两种模型和一些创建记录的代码对整个内容进行编码,然后进行查询,然后发布。
您是否可能忘记在架构中包含“ref”字段? 我刚遇到这个问题,在向我的架构添加 ref 字段后,它立即工作,无需重置数据库。 希望这些信息有帮助。
我在这里找到了一个示例: https : //mongoosejs.com/docs/3.0.x/docs/populate.html 。 虽然它是 3.0.x 版的文档,但我发现它甚至对我现在使用的 5.5.5 版也很有帮助。
如果您的数据非常小,请尝试从与 populate 和 main 相关的表中清除数据
我在这个问题上坚持了 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 :深入挖掘后,我发现更新不是解决方案。 我发现您需要包含要填充的所有模型。 例如:有一个连接到用户的国家模型。 然后在您的代码国家模型和用户模型中都应该像这样包含:
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;
首先,当您在创建一些集合后添加 populate 方法时会发生这种情况。
您可以为连接的模型(全部)发出新请求并创建新集合。 然后填充方法应该工作。
以前创建的模型仍将发送 null,但新创建的集合应返回填充数据。
当您尝试填充数据库中不再存在的内容时,有时会发生此错误。 由于这个原因,我遇到了这个错误。
我有一个类似的问题。 集合名称拼写错误。 我有一个名为 Currency 的集合,但正确的集合名称是 Currencies
我偶然发现了这个问题,问题是引用了一个已删除的文档。 如果可以,请重置您的数据库或仔细检查引用的 ID
当将 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 }
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.