4

I am having problems populating across 2 different models. User and Player. Each has a ObjectId stored for each other. My error occurs when I try to find the following populate from the User model.

User.find().populate('player_id')

Data of Users with Player_id

> db.getCollection('users').find({});
{ "_id" : ObjectId("58ea512576f3381d0cdf39a7"), "key" : "c7c7d3611f3d856f7a75eae5303e1cdf", "player_id" : ObjectId("59b3bff9605cbf7610c15837") }

Data of Players

> db.getCollection('players').find();
{ "_id" : ObjectId("59b3bff9605cbf7610c15837"), "user_id" : ObjectId("58ea512576f3381d0cdf39a7") }

User Model

var UserSchema = new Schema({
    name: String,
    player_id: {type: Schema.ObjectId, ref: "Player", default: null}
})

Player Model

var Player = new Schema({
    fname : String,
    sname : String,
    user_id: {type: Schema.ObjectId, ref: "User", default: null},
});

Full Error Message

{ CastError: Cast to number failed for value "59b3bff9605cbf7610c15837" at path "_id"
    at CastError (/var/www/norsemenfc.co.uk/node_modules/mongoose/lib/error/cast.js:27:11)
    at SchemaNumber.cast (/var/www/norsemenfc.co.uk/node_modules/mongoose/lib/schema/number.js:231:9)
    at SchemaNumber.SchemaType._castForQuery (/var/www/norsemenfc.co.uk/node_modules/mongoose/lib/schematype.js:1064:15)
    at SchemaNumber.castForQuery (/var/www/norsemenfc.co.uk/node_modules/mongoose/lib/schema/number.js:282:14)
    at /var/www/norsemenfc.co.uk/node_modules/mongoose/lib/schematype.js:991:18
    at Array.map (<anonymous>)
    at SchemaNumber.handleArray (/var/www/norsemenfc.co.uk/node_modules/mongoose/lib/schematype.js:990:14)
    at SchemaNumber.castForQuery (/var/www/norsemenfc.co.uk/node_modules/mongoose/lib/schema/number.js:280:20)
    at SchemaNumber.SchemaType.castForQueryWrapper (/var/www/norsemenfc.co.uk/node_modules/mongoose/lib/schematype.js:1016:17)
    at cast (/var/www/norsemenfc.co.uk/node_modules/mongoose/lib/cast.js:250:39)
    at model.Query.Query.cast (/var/www/norsemenfc.co.uk/node_modules/mongoose/lib/query.js:3109:12)
    at model.Query.Query._castConditions (/var/www/norsemenfc.co.uk/node_modules/mongoose/lib/query.js:1145:10)
    at model.Query.Query._find (/var/www/norsemenfc.co.uk/node_modules/mongoose/lib/query.js:1160:8)
    at /var/www/norsemenfc.co.uk/node_modules/kareem/index.js:250:8
    at /var/www/norsemenfc.co.uk/node_modules/kareem/index.js:23:7
    at _combinedTickCallback (internal/process/next_tick.js:131:7)
    at process._tickCallback (internal/process/next_tick.js:180:9)
  message: 'Cast to number failed for value "59b3bff9605cbf7610c15837" at path "_id" for model "users"',
  name: 'CastError',
  stringValue: '"59b3bff9605cbf7610c15837"',
  kind: 'number',
  value: 59b3bff9605cbf7610c15837,
  path: '_id',
  reason: undefined,

[EDIT]

Query to call Users

var mongoose = require('mongoose')
    User = mongoose.model('User'),
    Player = mongoose.model('Player');

module.exports = {
    getAll: function(passData){
        return User.find().populate('player_id') //Point where failure happens
            .then(function(data){
                passData.userDetails = data;
                return passData;
            });
    },

How the ObjectId's are saved

So I like to use mongoose.Types.ObjectId just to make sure, but even if i stored it as a string I don't believe this should happen.

    updateUserId: function (req, res) {
        var player_id = req.body.user,//string
            user_email = req.body.savePlayer; //string
        res.setHeader('Content-Type', 'application/json');

        return User.find({
            email: user_email
        }).exec({})
        .then(function(data){
                var user_id = data[0]._id; //ObjectId
                User.update({email: user_email}, {player_id: mongoose.Types.ObjectId((player_id))}, function (err) {
                    if(err)
                        res.send(JSON.stringify({status: 0}));
                    Player.update({_id: player_id}, {user_id: user_id}, function (err) {
                        if(err) {
                            res.send(JSON.stringify({status: 0}));
                        }else{
                            res.send(JSON.stringify({ status: 1 }));
                        }
                    })
                })
        });
    }

Edit 2

Route

    home: function (req, res) {
        var passData = {};

        api.getAll(passData)
            .then(api.getPlayersWithoutAUser)
            .then(function (passData) {
                res.render('admin/users', {
                    user: req.user,
                    title: 'Admin Users',
                    selectedAdminMenu: 'users',
                    passData: passData
                });
            })
            .catch(function (err) {
                console.error(err);
            });
    },

I am using Mongoose ^4.11.11

Jamie Hutber
  • 26,790
  • 46
  • 179
  • 291
  • Mongoose seems to think that `_id` in your `User` model should be a `Number`, and not an `ObjectId`. – robertklep Sep 10 '17 at 19:36
  • Ye... But what the hell does that mean ;) As its clearly not as I can see – Jamie Hutber Sep 10 '17 at 19:43
  • It means that for some reason, Mongoose thinks your schema looks like this: `{ _id : Number, ... }`. I can't reproduce the issue with the code you're posting and the database contents you're showing, so there must be something else that's causing it. – robertklep Sep 10 '17 at 19:49
  • Umm thanks very much for going through it. I will update the question with how I am saving this data as well, maybe there is an issue there. – Jamie Hutber Sep 10 '17 at 19:58
  • 1
    How do you know that the error happens exactly where you say it happens? `getAll()` doesn't have a `catch` statement so the error is handled somewhere upstream; isn't there any other code in between the `find` and the `catch` that could be causing it? Also, what is `passData`? – robertklep Sep 10 '17 at 20:37
  • 2
    You need to actually grep your source code for `{ _id: Number }` or `{ _id: { type: Number ...` or the like. The error is plainly stated and is in fact the only cause. You are chasing down red herrings. It's `_id` that is the problem and not any values you are actually assigning. The error is of course actually being thrown on **read** because the collection has `ObjectId` values yet the schema is defined with `Number`. If it's not immediately apparent on inspection of your schema, then you have installed a plugin at some stage which is actually responsible – Neil Lunn Sep 10 '17 at 21:30
  • @robertklep my understanding is that `mongoose` promises already pipe up the errors, so there is no need for a catch. But you are right to mention it as I haven't added this season of my code. Please see updated question. It also might be lack of knowledge, but passdata is just how I can pipe data through the chains. – Jamie Hutber Sep 10 '17 at 21:54
  • This codebase is 2 years btw. So @NeilLunn very astute of you. I found a file that referenced `_id: Number,` It exports the model `users`. So indeed, removing this `_id: Number,` removed the error. Indeed there was one place this file was being included, when it should not have been. I believe this is the correct answer and I should add that with a proper explanation. Thank you Neil and Robert for the help.. Very much thanks. – Jamie Hutber Sep 10 '17 at 21:59
  • @Jamie Hutber, why dont you add this as an answer and gain the points. I was looking, and had to read to the last comment, but slack allows answering your own questions. – blamb Mar 10 '20 at 17:59

0 Answers0