7

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

我有两个模式,用户和故事,如下所示。我正在尝试使用 Ref 选项为 Story 引用 User 以在查询中填充 - 我之前使用过 mySQL,因此想尝试复制 JOIN 语句。每当我尝试使用填充时,我只会返回 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');

用户模式.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,因为一个用户可以有很多故事,但每个故事只有一个用户,但我想我会先从这里开始。

4

9 回答 9

10

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

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

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

于 2019-03-17T12:42:14.920 回答
6

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

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

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

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

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

于 2013-11-11T22:47:16.893 回答
4

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

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

于 2019-05-04T02:41:17.293 回答
1

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

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

以前创建的模型仍将发送 null 但新创建的集合应返回填充数据。

于 2021-05-02T14:12:51.177 回答
0

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

于 2021-02-23T19:31:51.620 回答
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 更新了数据,现在“Populate”正在尝试更新数据:

 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;
于 2021-03-08T15:00:09.573 回答
0

当您尝试填充数据库中不再存在的内容时,有时会发生此错误。由于这个原因,我遇到了这个错误。

于 2022-02-22T12:31:30.700 回答
-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 }
});
于 2020-02-25T12:16:21.103 回答
-1

我偶然发现了这一点,问题是引用了一个已删除的文档。如果可以,请重置您的数据库或仔细检查引用的 id

于 2019-09-03T12:04:43.900 回答