Twig2let
Twig2let

Reputation: 27

KeystoneJS and Mongoose, advice on returning related documents via API

I have two Mongoose models defined by KeystoneJS:

// models/Movie.js

var Movie = new keystone.List('Movie');
Movie.add({
title: {
    type: Types.Text,
    initial: true,
    required: true,
    index: true,
    unique: true
}).relationship({
    path: 'trailers',
    ref: 'Trailer',
    refPath: 'movie'
});

// models/Trailer.js

var Trailer = new keystone.List('Trailer');

Trailer.add('Trailer', {
  title: {
    type: Types.Text,
    required: true,
    initial: true,
  }
}, 'Movie', {
    movie: {
        type: Types.Relationship,
        ref: 'Movie',
        many: false,
    }
})

There is a one-to-many relationship between Movie's and Trailer's.

I have written an API for Movies:

function findByTitle(req, res) {

    var promise = Movie.model.findOne({
        title: {
            $regex: new RegExp('^' + req.query.title + '$', "i")
        }
    })
    .exec();

    promise.then(function (item) {

        item.populateRelated('trailers', function (err, trailers) {
            item.trailers = trailers;
            res.status(200).send(item);
        })
    })
    .catch(function (err) {
        res.status(500).send(err.name);
    })
}

At the moment i'm leveraging KeystoneJS's populateRelated method, this grabs the associated trailers as expected. But as a Mongoose schema is immutable, how should you return the related trailers in the response? I understand you can pass strict: false as a schema option but I don't feel it's safe to override schema behaviour in this way.

It feels like i'm fighting the framework a little and thus likely approaching this problem the wrong way. What is the preferred approach to returning related field data via an API?

Update:

Would a separate API endpoint be the best way to go, for example:

api/movies/<movie_id>/trailers

Upvotes: 0

Views: 399

Answers (1)

Steve Holgado
Steve Holgado

Reputation: 12071

Try using populate like this:

function findByTitle(req, res) {

  Movie.model.findOne({
    title: {
      $regex: new RegExp('^' + req.query.title + '$', "i")
    }
  })
  .populate('trailers')
  .exec()
  .then(function (item) {
    res.status(200).send(item)
  })
  .catch(function (err) {
    res.status(500).send(err.name)
  })

}

Upvotes: 1

Related Questions