Заполненный запрос Mongoose возвращает все результаты с пропуском / ограничением - PullRequest
1 голос
/ 07 марта 2019

У меня есть следующий метод в небольшом приложении узла / экспресса:

async getAll(req, res) {
    const movies = await movieModel
        .find()
        .populate({path: 'genres', select: 'name'})
        .skip(0)
        .limit(15);
    return res.send(movies);
};

Со следующей схемой:

const MovieSchema = new mongoose.Schema({
    externalId: { required: true, type: Number },
    title: { required: true, type: String },
    genres: [{ ref: "Genre", type: mongoose.Schema.Types.ObjectId }],
    releaseDate: {type: Date},
    originalLanguage: {type : String},
    originalTitle: {type : String},
    posterPath: {type : String},
    backdropPath: {type : String},
    overview: {type: String},
    comments: [{ ref: "Comment", type: mongoose.Schema.Types.ObjectId }],
    votes: [VoteSchema]
}, {timestamps: true}
});

MovieSchema.virtual("averageNote").get(function () {
    let avg = 0;
    if (this.votes.length == 0) {
        return '-';
    }
    this.votes.forEach(vote => {
        avg += vote.note;
    });
    avg = avg / this.votes.length;
    return avg.toFixed(2);
});

MovieSchema.set("toJSON", {
    transform: (doc, ret) => {
        ret.id = ret._id;
        delete ret._id;
        delete ret.__v;
    },
    virtuals: true,
    getters: true
});

Однако запрос всегда возвращает все записи документа. Я также пытался добавить exec() в конце запроса или с .populate({path: 'genres', select: 'name', options: {skip: 0, limit: 15} }), но безрезультатно.

Я попробовал другую схему, которая более проста и skip / limit работала просто отлично, поэтому проблема, вероятно, исходит из моей схемы, но я не могу понять, где проблема.

Я также пытался прокомментировать виртуальное поле, но все же, limit и sort, где не используется.

Я предполагаю, что это от votes: [VoteSchema], так как я впервые использую это, но мой учитель рекомендовал использовать ref не рекомендуется в нереляционной базе данных. Кроме того, для вычисления среднего значения в виде виртуального поля у меня нет другого выбора.

РЕДАКТИРОВАТЬ: только что попробовал с votes: [{ ref: "Vote", type: mongoose.Schema.Types.ObjectId }] И я до сих пор не могу limit, ни skip

Версия узла: 10.15.1

MongoDB версия: 4.0.6

Mongoose версия: 5.3.1

Дайте мне знать, если я должен добавить любую другую информацию

1 Ответ

1 голос
/ 08 марта 2019

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

const movies = await movieModel
  .find()
  .skip(0)
  .limit(15)
  .populate({path: 'genres', select: 'name'}) // alternately .populate('genres','name')
  .exec()

Проблема в том, что .populate() на самом деле просто выполняет еще один запрос к базе данных, чтобы "эмулировать" a join . На самом деле это не имеет ничего общего с исходным .find(), поскольку все, что делает populate(), берет результаты из запроса и использует определенные значения для "поиска" документов в другом Коллекция, используя этот другой запрос. Важно отметить, что результаты приходят последний .

.skip() и .limit() с другой стороны - это модификаторы курсора и непосредственно часть базового драйвера MongoDB. Эти принадлежат к .find(), и поэтому должны быть в последовательности

Часть драйвера MongoDB в сборщике прощает:

.find().limit(15).skip(0)

также приемлемо из-за того, что опции передаются в «все сразу» , однако это хорошая практика , думать о ней как skip затем limit в таком порядке.

В целом, метод populate() должен быть последним элементом в цепочке после любых модификаторов курсора , таких как limit() или skip().

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...