繁体   English   中英

Mongoose 填充返回 null 或未定义

[英]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 相同。 所以我认为解决方法是:

  1. 确保您在 users 集合中有一个有效的用户记录
  2. 确保您的测试故事记录的 story.author_id 匹配
  3. 确保您通过故事 ID 而不是 author_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM