1

I'm working on a node app (with IOS front end) right now and stumbled upon this issue. I used mongodb together with mongoose. I have this route, /get that receives the correct user id and tries to find all 'Voots' with that same user id. This is what a 'Voot' looks like:

{
"_id": "59db9fa2659bb30004899f05",
"title": "Pizza!",
"body": "hoppakeeee",
"user": {
  "__v": 0,
  "password": "$2a$10$Rwb5n7QoKaFaAOW37V0aWeEeYgfn6Uql474ynUXb83lHi7H2CuB1u",
  "email": "noelle.schrikker@planet.nl",
  "name": "Noelle Schrikker",
  "_id": "59db9ecf659bb30004899f04"
},
"__v": 0,
"downVotes": [],
"upVotes": []

},

As you can see, it has a property called user which is a user object containing a name, email, password and _id.

I do this with my request:

// Send all voots from the specific user
        Voot.find({"user._id": userId}, function(err, voots) {
            if (err) {
                console.log(err);
                res.status(400).send(err)
                res.end()
            }

            if (voots) {
                res.status(200).send(voots)
                res.end()
            }
        })

I try to find all voots with their user having the property of userId (this is the correct user ID). However, this doesn't work. I tried finding it by "user.email" which does work. I think it has something to do with the _ before id. Any comment is appreciated!

Voot shema:

var vootSchema = new mongoose.Schema({
    title: String,
    body: String,
    user: {
        type: mongoose.Schema.Types,
        ref: 'user'
    },
    upVotes: [String],
    downVotes: [String]
})

var Voot = mongoose.model('voot', vootSchema)

Userschema:

var userSchema = new mongoose.Schema({
    name: String,
    email: String,
    password: String
})

var User = mongoose.model('user', userSchema)

3 Answers3

1

I would assume that _id of user object is not a string. That said you need to modify your query to use ObjectId instead of string:

     Voot.find({"user._id": ObjectId(userId)}, function(err, voots) {
        if (err) {
            console.log(err);
            res.status(400).send(err)
            res.end()
        }

        if (voots) {
            res.status(200).send(voots)
            res.end()
        }
     })

If you don't want to change your query, you could change your user schema, so that _id is string. Then your query should start working:

var userSchema = new mongoose.Schema({
    _id: { type: String },
    name: String,
    email: String,
    password: String
})

var User = mongoose.model('user', userSchema)
Ivan Vasiljevic
  • 5,478
  • 2
  • 30
  • 35
  • Unfortunately, this isn't the solution either. Because finding an object without the `ObjectId()` method does normally work in my case. This one should't be any different. –  Oct 09 '17 at 17:15
  • Well, you could change `_id` in user Schema to string, and then your query should work. – Ivan Vasiljevic Oct 09 '17 at 17:32
  • I could try that, but I just saw a video of a guy that explains that mongoose automatically modifies the input for the `_id` to match the type, so it doesn't matter how I hand it in. This is also why it normally does work. Yay mongoose! –  Oct 09 '17 at 17:37
  • I am not sure about that. You can find a lot of questions with similar problems. And this is not issue with mongoose, but with MongoDB itself. https://stackoverflow.com/questions/7878557/cant-find-documents-searching-by-objectid-using-mongoose – Ivan Vasiljevic Oct 09 '17 at 17:39
  • Tried putting in the: `type: String` but this doesn't work either, it just return an empty array –  Oct 09 '17 at 17:50
0

Use just user in your query rather than user._id:

Voot.find({ "user": userId }, function(err, voots) {
  // Callback code
})

The id or the referenced user is stored in the user field. The user sub-document, and therefore the user._id field, will only be available after population.

Steve Holgado
  • 11,508
  • 3
  • 24
  • 32
  • In your **vootSchema**, your user field type should be of type **ObjectId**. Currently you just have: **mongoose.Schema.Types** – Steve Holgado Oct 09 '17 at 17:44
  • But then I only put in the ID, this way I have to whole user object. –  Oct 09 '17 at 17:47
  • What do you mean by population? –  Oct 09 '17 at 17:48
  • You would store the id of a user and then that field gets replaced with the referenced user document using population. I thought that’s what you were trying to achieve. – Steve Holgado Oct 09 '17 at 17:53
  • Aaaah, I think I understood wrong, by just storing the `mongoose.schema.types.objectId` you can access the User object using population? (instead of storing just `mongoose.schema.types`) –  Oct 09 '17 at 17:59
0

Got it! I added .ObjectId in the Voot schema, now I can access the User object using population. I can now find the Voot by using:

Voot.find({“user”: userId}).populate(‘user’) .exec()

Thanks for all the answers!