Как заполнить массив экземпляров модели внутри вложенного документа? MongoDB Mongoose - PullRequest
0 голосов
/ 12 января 2020

У меня есть вложенный документ, который вложен в массив. Внутри этого поддокумента у меня есть ссылки на другие модели. Используя методы .Find и .Populate, я могу получить целые объекты для отдельных моделей, на которые есть ссылки в поддокументе (см. «Стоп» ниже), но не массив экземпляров модели, факты / рекомендации. Для Фактов / Рекомендаций я получаю массив объекта _ids. Я, вероятно, могу просто взять эти _ids и сделать еще один запрос, но это кажется грязным.

Есть ли способ заполнить массив? Нужно ли использовать Aggregate + $ lookup? Есть ли более простой способ go реструктурировать схему, чтобы упростить это?

Спасибо за все и за любую помощь!

Мой поддокумент под названием TourStop:

const mongoose = require('mongoose');

const Schema = mongoose.Schema;

const TourStopSchema = new Schema({
    stop: {
        type: Schema.Types.ObjectId,
        ref: 'Stop',
        required:[true, 'must have a Stop'],
    },
    mandatory: {
        type:Boolean,
        default: false
    },
    check_in_time: {
        type: Number,
        default: 0
    },
    order: {
        type:Number,
        required: [true, 'Must have an order']
    },
    facts: [{
        type: Schema.Types.ObjectId,
        ref: 'Fact'
    }],
    recommendations: [{
        type: Schema.Types.ObjectId,
        ref: 'Recommendation'
    }]
});


module.exports = TourStopSchema;

TourStops живет внутри Tour:

const mongoose = require('mongoose');
const TourStopSchema = require('../subdocs/tour_stop');
const Schema = mongoose.Schema;

const tourSchema = new Schema({
    name: {
        type:String,
        required:[true,'Name is required!'],
        unique: true
    },
    city: {
        type: String,
        required: [true, 'City is required!']
    },
    tourStops:[TourStopSchema]
});

const Tour = mongoose.model('Tour', tourSchema);
module.exports = Tour;

Stop Схема которая заполняется просто отлично.

const mongoose = require('mongoose');
const LocationSchema = require('../subdocs/location');
const ImageSchema = require('../subdocs/image');
const Schema = mongoose.Schema;

const stopSchema = new Schema({
    name:{
        type: String,
        required:[true,'Must have a name!']
    },
    location:LocationSchema,
    categories: {
        type: [String],
        default:[]
    },
    images:{
        type:[ImageSchema],
        default:[]
    }
});

const Stop = mongoose.model('Stop', stopSchema);
module.exports = Stop; 

И схема фактов, которая не заполнена правильно, вместо этого возвращает массив строк с _ids

Факт:

const mongoose = require('mongoose');
const ImageSchema = require('../subdocs/image');
const Schema = mongoose.Schema;

const factSchema = new Schema({
    stop: {
        type: Schema.Types.ObjectId,
        ref:'Stop',
        required:[true, 'A Fact must have a Stop!'],
    },
    description: {
        type: String,
        required: [true,'A Fact must have a description!']
    },
    images: {
        type:[ImageSchema],
        default:[]
    }
});

const Fact = mongoose.model('Fact', factSchema);
module.exports = Fact;

И я запускаю проверить, правильно ли подключена схема для получения всех атрибутов TourStop:

it('saves a full relation graph', (done) => {
    User.findOne({ first_name: 'Dean' })
        .populate({
            // in that user find the tours property and load up all tours
            path: 'tours',
            // inside of all those tours, find the tourstops property and load all associated stops
            populate: {
                path: 'tour_stops.facts',
                model: 'Fact'
            },
            populate: {
                path: 'tour_stops.stop',
                model: 'Stop'
            }
        })
        // .populate('tours.tour_stops[0].facts')
        .then((user) => {
            // console.log(user.tours[0].tour_stops[0].stop);
            console.log(user.tours[0].tour_stops[0]);
            // console.log(Array.isArray(user.tours[0].tour_stops[0].facts))
            assert(user.first_name === 'Dean' );
            assert(user.tours.length === 1);
            assert(user.tours[0].name === "Awesome New Tour");
            assert(user.tours[0].tour_stops[0].stop.name === 'Jaffa Clock Tower');
            // assert(user.tours[0])
            // assert(user.blogPosts[0].title === 'JS is Great');
            // assert(user.blogPosts[0].comments[0].content === 'Congrats on great post!' );
            // assert(user.blogPosts[0].comments[0].user.name === 'Joe' )
            done();
        })
    })

1 Ответ

1 голос
/ 12 января 2020

Вы можете использовать следующий код для заполнения туров, остановок, фактов и рекомендаций. Обратите внимание, что в свойстве model мы должны указывать не строковое значение, а саму модель. Поэтому вам нужно импортировать их в свой код.

  User.findOne({ first_name: "Dean" })
    .populate({
      path: "tours",
      populate: {
        path: "tourStops.stop",
        model: Stop
      }
    })
    .populate({
      path: "tours",
      populate: {
        path: "tourStops.facts",
        model: Fact
      }
    })
    .populate({
      path: "tours",
      populate: {
        path: "tourStops.recommendations",
        model: Recommendation
      }
    })
    .then(user => {
       console.log(user);
    });
...