0

I'm creating a website with tours, that must be specified by categories, but I don't know how to load only tours related to categories. I tried to load them with find().where() but I get all tours loaded in all 3 categories.

KeystoneJS doesn't have documentation about any sort methods, I found only two examples, that don't work for me.

My trips.js:

let keystone = require('keystone');
let async = require('async');

exports = module.exports = function (req, res) {
    let view = new keystone.View(req, res);
    let locals = res.locals;

    // Set locals
    locals.section = 'tours';
    locals.filters = {
        trip: req.params.trip,
    };
    locals.data = {
        trips: [],
        category: [],
    };

    view.on('init', function (next) {


        keystone.list('TripCategory').model.find().sort('name').exec(function (err, results) {
            locals.data.category = results;
            next(err);

            async.each(locals.data.category, function (category, next) {

                keystone.list('Trip').model.find().where('category', category.name).exec(function (err, results) {
                    locals.data.trips = results;
                    console.log(locals.data.trips);
                    next(err);
                });

            });
        });

    });


    view.render('trips');
};

My Trip.js:

let keystone = require('keystone');
let Types = keystone.Field.Types;

let Trip = new keystone.List('Trip', {
    map: { name: 'title' },
    singular: 'Trip',
    plural: 'Trips',
    autokey: { path: 'slug', from: 'title', unique: true },
});

Trip.add({
    title: { type: String, required: true },
    content: {
        brief: { type: Types.Html, wysiwyg: true, height: 150 },
        extended: { type: Types.Html, wysiwyg: true, height: 400 },
    },
    category: { type: Types.Relationship, ref: 'TripCategory' },
    duration: { type: Types.Html, wysiwyg: true },
    distance: { type: Types.Html, wysiwyg: true },
    price: { type: Number },
    images: { type: Types.CloudinaryImages },
    coverImage: { type: Types.CloudinaryImage },
});

Trip.register();

My TripCategory.js:

let keystone = require('keystone');
let Types = keystone.Field.Types;

let TripCategory = new keystone.List('TripCategory', {
    autokey: { from: 'name', path: 'slug', unique: true },
});

TripCategory.add({
    name: { type: String, required: true, unique: true },
    description: { type: Types.Html, wysiwyg: false, height: 500 },
});

TripCategory.relationship({ ref: 'Trip', path: 'trips', refPath: 'category' });

TripCategory.register();

  • Could you post the code for your models? This should be easy to accomplish without the additional loop and multiple db queries. I def wouldn't go with this solution. – silencedogood Sep 11 '19 at 15:04
  • @silencedogood I edited my post and added models. – Michael Shkarubski Sep 11 '19 at 16:48
  • It looks like you want to return all the trips, grouped by whatever category the trip is in, is that correct? Just trying to be clear before I spend time building the query. – silencedogood Sep 12 '19 at 13:45
  • It seems strange that you would re-set the value of `locals.data.trips` each time in the loop. It also seems arbitrary to loop in the first place. Why not just `keystone.list('Trip').model.find().sort('category')` ?? – silencedogood Sep 12 '19 at 13:52
  • @silencedogood I need Tour.js fields to be displayed on the screen, so I do ```keystone.list('Trip').model.find().where('category').exec(function (err, results) { locals.data.trips = results; console.log(locals.data.trips); next(err); });``` – Michael Shkarubski Sep 12 '19 at 17:17
  • I don't see a Tour.js... All I see is Trip.js and TripCategory.js. I'm assuming you're talking about Trip.js?? – silencedogood Sep 12 '19 at 17:52
  • @silencedogood sorry, I talked about Trip.js, my fault. – Michael Shkarubski Sep 12 '19 at 18:21

1 Answers1

0

You should just be able to use a regular find query, along with populate.

keystone.list('Trip').model.find()
  .populate({path: 'category', options: {sort: {'name'}}})
  .exec(function(err, results) {
      locals.data.trips = results;
   })

This will get all trips, along with their corresponding category info, and sort them by the category name. If this syntax gives you issues (due to keystonejs using an older version of mongoose) try some of the different syntax versions that have continued to evolve. Here's a post that details them

silencedogood
  • 3,209
  • 1
  • 11
  • 36