Доступ к дочерним методам в parent для mongoose успешно выполняется в массиве и завершается ошибкой с одним дочерним элементом - PullRequest
0 голосов
/ 06 октября 2019

ОБНОВЛЕНИЕ: Решение находится в нижней части вопроса

У меня есть экспресс-сайт с использованием мангусты.

Я бы очень сильно сказал, что у меня есть взрослые, дети и домашние модели. Когда я создаю методы для детей, я могу вызывать их изнутри для взрослых и получать результаты. Я также могу позвонить им из моих просмотров .ejsОднако, когда я создаю методы на дому, я могу получить результат только из моих представлений .ejs и получить неопределенный при вызове изнутри методов для взрослых. Пример кода следующий.

adult.js

const mongoose  = require('mongoose');
const adultSchema = mongoose.Schema({
    name: { type: String },
    size: {type: String},
    kids: [{type: mongoose.Schema.Types.ObjectId, ref: 'Kid', required: true}]
    house:{type: mongoose.Schema.Types.ObjectId, ref: 'House', required: true}
});

adultSchema.method({
  getKidsDescription: function() {
     if (this.kids.length < 1) {
     return 'No kids yet';
   } else {
     let ev = 'Kids, aged: ';
     let kds = this.kids;
     kds.forEach(function(k){
        ev = ev + 'k.getAge()' // works
     })
     return ev;
   }
 },
 getHouseDescription: function(){
    return 'A fabulous house on '+this.house.getFullStreet(); // does not work
 }
})

module.exports = mongoose.model('Adult', adultSchema);

kid.js

const mongoose  = require('mongoose');
const kidSchema = mongoose.Schema({
    name: { type: String },
    size: {type: String},
    birthdate: {type:Date}
});

kidSchema.method({
  getAge: function() {
     return (Math.floor(new Date() - this.birthdate)/(1000*60*60*24*365))
  },
})

module.exports = mongoose.model('Kid', kidSchema);

house.js

const mongoose  = require('mongoose');
const houseSchema = mongoose.Schema({
    name: { type: String },
    city: {type: String},
    street: {type:String}
});

houseSchema.method({
  getFullStreet: function() {
     return this.street + ' Road';
  },
})

module.exports = mongoose.model('House', houseSchema);

Когда я делаю запрос для Adult, это выглядит так:

controller.js

exports.main = async (req, res, next) => {
  if (req.theAdult) {
    try {
      const found = await db.fetchAdult(req.theAdult._id)
      res.render('/main', {
          //theHouse: found.house    //below I show this working
      });
    } catch(e) {
      throw new Error(e.message)
    }
  } else {
      res.redirect('/');
  }
}

db.js

exports.fetchAdult = (id) => {
  return Adult.findById(id)
      .populate({ path: 'kids'})
      .populate({ path: 'house'})
      .exec()
      .then(doc => {
          return doc;
  });
}

Предполагая, что дом передается для просмотра как объект при визуализации (закомментировано выше), это работает

view.ejs

   <p> <%= theHouse.getFullStreet() %></p> 

Если предположить, что дом, заполненный при вызове для загрузки Adult, возвращает неопределенное значение.

view.ejs

   <p> <%= theAdult.house.getFullStreet() %></p> 

В то же время обе эти работы

view.ejs

   <ul> <% theAdult.kids.forEach(function(k) { %>
          <li><%= k.getAge() %> </li>
        <% }); %>
   </ul>

   <p> <% theAdult.getKidsDescription() %> </p>

Я не понимаю, как работают вызовы методов для объектов в массиве иработать в представлении, но не работать для объектов в массиве. Это ошибка одного ребенка (для меня). Если бы он не работал в представлении, я бы предположил, что метод getFullStreet() был проблемой, но он работает в представлении. Если бы методы массива не могли быть вызваны в родительском объекте, я бы предположил, что проблема заключалась в попытке доступа к getFullStreet() в родительском объекте.

Чего мне не хватает?

РЕШЕНИЕ Я получал theAdult в моем звонке для показа view.ejs, но тогда я действительно полагался на currentAdult, которыйотносится к req.adult и не имеет заполненных полей. Мое решение состояло в том, чтобы добавить предварительный хук к схеме для взрослых, которая всегда заполняет дом при поиске.

в adult.js

adultSchema.pre('find', function() {
  this.populate('house')
})

1 Ответ

0 голосов
/ 07 октября 2019

Вы пытались передать гидратированный Взрослый? Он может видеть только ObjectID без каких-либо других данных или методов.

...