如果这是一个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,因为用户可以有很多故事,但每个故事只有一个用户,但我想我会先从这里开始。
答案 0 :(得分:3)
由于您的示例包含的原始对象ID甚至没有被引用为有效的javascript字符串,因此很难理解您的问题中的错误与代码中的错误,但大多数情况下您的第二个查询看起来应该有效。我怀疑你是在混淆你的ObjectId值。您正在为您的故事和您的用户使用相同的ObjectId,但这不起作用:
author_id: mongoose.Types.ObjectId(528149b38da5b85003000002),
这与您用于查找故事的ID相同。所以我认为修复是:
如果仍然无法使其正常工作,请在单个.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 }
});