Найти документ на основе ссылки на родителя у ребенка

1

Есть 2 коллекции Movie и Rank Movie. Эти 2 коллекции имеют ссылку на отношения.

Movie model

var mongoose = require('mongoose');

var movieSchema = new mongoose.Schema({
    m_tmdb_id: {
        type: Number,
        unique: true,
        index: true
    },
    m_adult: {
        type: Boolean
    },
    m_backdrop_path: {
        type: String,
    },
    m_title: {
        type: Number
    },
    m_genres: {
        type: Array
    }

});
var MovieModel = mongoose.model('Movie', movieSchema);
module.exports = {
    movie: MovieModel
}

Rank movie model

var mongoose = require('mongoose');
var rankMovieSchema = new mongoose.Schema({
    movie: {
        type: mongoose.Schema.Types.ObjectId,
        ref: 'Movie',
        unique: true
    },
    rank: {
        type: Number
    },
    count: {
        type: Number
    }
});
var RankMovieModel = mongoose.model('RankMovie', rankMovieSchema);
module.exports = {
    rankmovie: RankMovieModel
}

Мне нужно выбрать все элементы из фильма ранга коллекции, имеющие определенный заголовок [Условие в коллекции фильмов]. Как я могу это достичь?

Теги:
mongoose
mongodb-query

1 ответ

2
Лучший ответ

На самом деле "лучший" способ сделать это скорее использует .aggregate() и $lookup для "объединения" данных и "фильтрации" в условиях соответствия. Это очень эффективно, так как MongoDB фактически выполняет все это на самом "сервере" по сравнению с выдачей "множественных" запросов как .populate().

MovieModel.aggregate([
  { "$match": { "m_title": m_title } },
  { "$lookup": {
    "from": RankMovieModel.collection.name,
    "localField": "_id",
    "foreignField": "movie",
    "as": "rankings"
  }}
])

Примечание. RankMovieModel.collection.name - отличный способ получить название базовой RankMovieModel.collection.name из Model зарегистрированной в Mongoose. Поскольку операция находится на "сервере", MongoDB нуждается в "реальном имени коллекции", поэтому мы можем либо "жестко", либо просто получить его от информации, зарегистрированной на самой модели. Как это делается здесь.

Если есть "партии" ранжирования, то лучше всего использовать $unwind, который создаст документ для каждого связанного элемента "рейтинг":

MovieModel.aggregate([
  { "$match": { "m_title": m_title } },
  { "$lookup": {
    "from": RankMovieModel.collection.name,
    "localField": "_id",
    "foreignField": "movie",
    "as": "rankings"
  }},
  { "$unwind": "$rankings" }
])

Существует также особый подход к тому, как MongoDB занимается "присоединением" документов, чтобы не нарушать предел BSON на 16 МБ. Так ведь это особая вещь происходит, когда $unwind непосредственно следует за $lookup этапа трубопровода:

    {
        "$lookup" : {
            "from" : "rankmovies",
            "as" : "rankings",
            "localField" : "_id",
            "foreignField" : "movie",
            "unwinding" : {
                "preserveNullAndEmptyArrays" : false
            }
        }
    }

Таким образом, $unwind фактически "исчезает" и вместо этого "свернут" в самом $lookup, как если бы это была "одна" операция. Таким образом, мы не создаем "массив" непосредственно в родительском документе, который в крайних случаях может превышать 16 МБ со многими "связанными" элементами.


Если у вас нет MongoDB, который поддерживает $lookup (MongoDB 3.2 minunum), тогда вы можете использовать "virtual" с .populate() вместо этого (требуется минимум Mongoose 4.5.0). Но обратите внимание, что это фактически выполняет "два" запроса на сервер:

Сначала добавьте "виртуальную" в схему:

movieSchema.virtual("rankings",{
  "ref": "Movie",
  "localField": "_id",
  "foreignField": "movie"
});

Затем выполните запрос с помощью .populate():

MovieModel.find({ "m_title": m_title })
  .populate('rankings')
  .exec()
  • 0
    Спасибо за вашу помощь. Мои требования немного отличаются. Обновлен вопрос.
  • 0
    @Muhsin Это очень грубо. Вопрос совершенно другой. Вы должны вернуться к исходному вопросу и задать новый вопрос . Изменение вашего вопроса таким образом не является вежливым способом вести себя здесь. У вас есть ответ на вопрос, который вы на самом деле задали. Все остальное - новый вопрос . С удовольствием смотрю на новые вопросы, пока этот остается неизменным.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню