mongoose find a document by reference property

Refresh

November 2018

Views

7.4k time

8

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.

1 answers

6

В вашей coupleмодели, person1является ObjectID (я знаю , что вы знаете), поэтому он не имеет , очевидно , никакой собственности .firstname.

На самом деле лучший способ для достижения этой цели, это найти пользователя по его первым именем, а затем запросить пару, с idпользователя.

Этот метод может / должен стоять в coupleмодели как статический метод (упрощенный код образца):

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
}

Так же , как этот Exemple .

EDIT: Кроме того, обратите внимание , что ссылка должна быть _id(так что вы не могли бы хранить с первым именем, что было бы неплохо в любом случае).

Учитывая ваши изменения:

Person._idэто может быть, Stringи ссылка является ObjectId, если так, то попробуйте:

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

Кроме того , вы переменная personи не Person. Попробуйте войти , personчтобы увидеть , если вы получаете что - то.

Наконец, мой пример кода очень прост, не забывайте обрабатывать ошибки и все (см ссылку я дал вам выше, что является полным).