Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mongoose find a document by reference property

I have a first model Person:

var personSchema    = new Schema({
    firstname: String,
    name: String
});
module.exports = mongoose.model('Person', personSchema);

And a second model Couple:

var coupleSchema    = new Schema({
    person1: [{ type: Schema.Types.ObjectId, ref: 'Person' }],
    person2: [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});
module.exports = mongoose.model('Couple', coupleSchema);

I find a couple with a person ObjectId:

    Couple.find({
        'person1': req.params.objectid
    })
    .populate({
        path: 'person1 person2'
    })
    .exec(function (err, couple) {
        if (err)
            res.send(err);
        res.json(couple)
    });

But I would like to find a couple by giving a firstname and not an ObjectId of a Person, something like that:

    Couple.find({
        'person1.firstname': "Bob"
    })
    .populate({
        path: 'person1 person2'
    })
    .exec(function (err, couple) {
        if (err)
            res.send(err);
        res.json(couple)
    });

But it is always empty...

Anyway to solve this?

Thank you for any feedback.

EDIT

I just implemented the answer:

Let's see my Couple model now:

var Person      = require('mongoose').model('Person');
var coupleSchema    = new Schema({
    person1 : [{ type: Schema.Types.ObjectId, ref: 'Person' }],
    person2 : [{ type: Schema.Types.ObjectId, ref: 'Person' }]
});

coupleSchema.statics.findByUsername = function (username, callback) {
  var query = this.findOne()

  Person.findOne({'firstname': username}, function (error, person) {
    query.where(
      {person1: person._id}
    ).exec(callback);
  })
  return query
}

module.exports = mongoose.model('Couple', coupleSchema);

With this usage:

Couple.findByUsername(req.params.username, function (err, couple) {
        if(err)
            res.send(err);
        res.json(couple);
    });

That works! Thank you for your answer and edits.

like image 940
Thomi Avatar asked Mar 24 '16 13:03

Thomi


People also ask

What does REF do in mongoose?

The ref option is what tells Mongoose which model to use during population, in our case the Story model. All _id s we store here must be document _id s from the Story model. Note: ObjectId , Number , String , and Buffer are valid for use as refs.

What does findById return in mongoose?

Return value findById returns the document where the _id field matches the specified id . If the document is not found, the function returns null .

What is __ V in MongoDB?

The __v field is called the version key. It describes the internal revision of a document.

What is $GTE in mongoose?

$gte selects the documents where the value of the field is greater than or equal to (i.e. >= ) a specified value (e.g. value .)


1 Answers

In your couple model, person1 is an ObjectID (I know you know it), so it has no obviously no property .firstname.

Actually the best way to achieve this, is to find the user by it's first name, and then query the couple, with the id of the user.

This method could/should stand in the couple model as a static method (simplified code sample):

couple.statics.findByPersonFirstname = function (firstname, callback) {
  var query = this.findOne()
 
  Person.findOne({firstname: firstname}, function (error, person) {
    query.where($or: [
      {person1: person._id},
      {person1: person._id}
    ]).exec(callback);
  })

  return query
}

Just like this exemple.

EDIT: Also note that the ref must be the _id (so you couldn't store with the first name, that would be a bad idea anyway).

Considering your edit:

Person._id is maybe a String and the reference is an ObjectId, if so, try:

{person1: mongoose.Types.ObjectId(Person._id)}

Also, your variable is person and not Person. Try to log person to see if you get something.

Finally, my code sample is really simple, don't forget to handle errors and all (see the link I gave you above, which is complete).

like image 118
Cohars Avatar answered Oct 20 '22 10:10

Cohars