Patrick Connors
Patrick Connors

Reputation: 6065

Mongoose one to one query returning nulll

I'm using mongoose to create two models, user and child, that are able to relate to each other. In the mongo shell I am able to query children with a user._id parameter and return an array of children whose admin property is the specified user. Additionally, in my node app, I'm able to query my db of children based on their other properties such as name. However, when I perform the following query, an empty array is returned. It should be noted that user._id property is the string of a user that is indeed an admin. Additionally, simply changing the query parameter to name and a corresponding value results in a successful query. Am I missing something obvious?

User.js

var UserSchema = mongoose.Schema({
    username: {
        type: String,
        index:true
    },
    password: {
        type: String
    },
    email: {
        type: String
    },
    name: {
        type: String
    },
});

Child.js

var childSchema = mongoose.Schema({
  Name:{
    type:String,
    required:true
  },
  Address:{
    type:String,
    required: true
  },
  Admin : { type: Schema.Types.ObjectId, ref: 'User' },
});

Query (returns null):

var ObjectId = require('mongoose').Types.ObjectId;
Child.find({Admin:ObjectId(user._id)},callback);

Parameters used in creation of child:

 { "Name" : "First Child", "Address" : "Sample Address", "Admin" : req.user._id }

Child Sample returned from mongo shell:

{
    "_id" : ObjectId("59519c30c904d23ea2e9f58f"),
    "Name" : "First Child",
    "Address" : "Sample Address",
    "Admin" : ObjectId("594d9e5f9d3b199b781015a3"),
    "__v" : 0
}

Sample Parent:

{
    "_id" : ObjectId("594d9e5f9d3b199b781015a3"),
    "name" : "User",
    "email" : "[email protected]",
    "username" : "user",
    "password" : "$2a$10$.o9k2yyUMlTpecKVkqWYr.Pg8TMCGIZrexHb3Ce//5ILpC9CDKEeS",
    "__v" : 0
}

Upvotes: 0

Views: 64

Answers (2)

sidgate
sidgate

Reputation: 15234

Simple typo. Schema defines field as Admin, while you are querying with admin. Field names are case sensitive. Code should be:

var ObjectId = require('mongoose').Types.ObjectId;
Child.find({Admin:ObjectId(user._id)},callback);

Upvotes: 1

Neil Lunn
Neil Lunn

Reputation: 151072

You seem to have a misconception of how to address property in the collection as well as not understanding that the ObjectId type is in fact already defined in your schema, and as such mongoose will "cast" this to the defined type for you in a .find() operation, or similar operations that are able to reference the schema.

Therefore the correct statement should be:

Child.find({ "Admin": user._id },callback);

Things you need to be aware when doing this are:

  • Make sure that your input's are valid and of the values you expect. It is always best to debug, by passing explicit values when you have a problem:

    Child.find({ "Admin": "594d9e5f9d3b199b781015a3" },function(err, result) {
      if (err) throw err; console.log(result) 
    })
    
  • Mongoose "pluralizes" the given model name when it determines the actual collection name to address. In particular, if you have data already defined which you then create a schema for at a later date, then you likely need to name that collection explicitly, since it may not be the same as what mongoose is choosing:

    mongoose.model("Child", childSchema, "child")
    

In that second case, mongoose would choose "children" by default, so the explicit name is needed to the actual collection when named differently. The common example here is a model "Person" would actually become "people".

As a final note, it's a good idea to turn on "debugging" to see what Mongoose is actually doing when sending your queries/operations to MongoDB.

mongoose.set("debug", true)

Understanding these things is how you avoid future errors, and generally gain further understanding of how things work.

Upvotes: 2

Related Questions