Reputation: 21278
I'm working on an application where you upload images and the uploaded images are displayed side by side in thumbnails. I want to implement filter possibilities, so that one can show images in a different order, like for example the image with most points first in descending order.
I'm having troubles to come up with a good solution for how this should be done, and the only thing I can think of is creating a new route for this (the same as the one I'm using now, below), but different sorting.
This is however DRY coding and not a good thing especially because I have plans for even more sorting options.
I have two questions regarding this:
Model for Images:
var ImageSchema = new Schema({
name : String,
size : Number,
title : String,
body : String,
buf : Buffer,
date: { type: Date, default: Date.now },
comments : [CommentSchema],
meta : {
upvotes : Number,
downvotes : Number,
favs : Number,
uniqueIPs : [String],
tags : [String]
}
});
Route for rendering images:
app.get('/images/:num?', function(req, res){
var query = model.ImagePost.find({});
query.where('date').lte(new Date());
query.desc('date');
query.exec(function (err, images) {
if (err) {
console.log(err);
// do something
}
var query = tagModel.Tag.find({});
query.exec(function (err, tags) {
if (err) {
console.log(err);
// do something
}
query = albumModel.Album.find({});
query.exec(function (err, albums) {
if (err) {
console.log(err);
// do something
}
res.render('blogs/index', { title: 'Images', imageList: images, tagList: tags, albumList: albums, dateFormatter: dateFormatter });
});
});
});
});
Jade file (partial) that's rendering out the images to the client:
#image
div.post
input(type='hidden', value=image.name + ',' + image.body + ',' + image.date);
button.imageValue(value= image.name, name= image._id)
div.albumImgChooseCover +
img.images(src='../images/' + image.name)
div.postDesc
a#single_1(href='../images/' + image.name, title= image.body + ' (Published: '+ formatter.format(image.date) +')')
img.zoom(src='../img/zoom.png')
a.various#box1(data-fancybox-type='iframe', href='/image/' + image._id.toHexString())
img.comments(src='../img/comments.png')
p.nrOfComments= image.comments.length
h2.subtitle= image.title
p.postDescContent= 'Points' + ': ' + (image.meta.upvotes - blog.meta.downvotes)
form.deleteButtonBox(action='/image/delete/' + image._id.toHexString(), method='POST')
input(class='deleteButton', type='submit', value='x')
a.various#box2(data-fancybox-type='iframe', href='/image/edit/' + blog._id.toHexString()) Edit
- if (image.meta.tags)
ul.tags
h3 Tags:
each tag in tagList
- if (image.meta.tags.indexOf(tag._id) != -1)
a(href='/tag/' + tag._id.toHexString())
span.tagInImage= tag.name
Upvotes: 1
Views: 880
Reputation: 312075
Adding a sort=<value>
parameter to your existing route URL is the typical way to handle this.
As far as sorting by points, now that Mongo 2.2 is available you can use the aggregation framework for that:
ImageSchema.aggregate([
{$project: {
name: 1,
size: 1,
// ... more fields you want included
points: {$subtract: {['$meta.upvotes', '$meta.downvotes']}}
}},
{$sort: {points: -1}}
], function(err, results) {
console.log(results);
});
Upvotes: 1