1

This is about likes and dislikes on comments. I'd like to sort comments by likeness, so a comment with more likes will appear first. The issue is that comments with dislikes appear before than comments with no dislikes.

What i want:

  • Comment A : 1 like 0 dislikes
  • Comment B : 0 like 0 dislike
  • Comment C : 0 like 1 dislike

What I'm actually getting:

  • Comment A : 1 like 0 dislikes
  • Comment C : 0 like 1 dislike
  • Comment B : 0 like 0 dislike

My mongo query on my meteor helper:

Missatges.find({ topic: 'xxx' }, { sort: { like:{ $size: -1}, dislike:{ $size: 1}, date: -1 } }).fetch();

Note that I use $size because like and dislike are arrays of user _id's. Here my comment schema:

author: {
    type: String

},
authorId: {
    type: SimpleSchema.RegEx.Id
}
isAnswer: {
    type: Boolean
},
parentId: {
    type: SimpleSchema.RegEx.Id,
    optional: true
},
date: {
    type: Date
},
topic: {
    type: String
},
likes: {
    type: [SimpleSchema.RegEx.Id]
},
dislikes: {
    type: [SimpleSchema.RegEx.Id]
},
answers: {
    type: [SimpleSchema.RegEx.Id],
    optional: true
},
text: {
    type: String,
    max: 900,        
}
Vice Sallés
  • 97
  • 2
  • 10

1 Answers1

1

According to the answer to this question you can't use $size to sort in mongo. One solution is to fetch the matching documents and sort them in the helper. Here's an example (note this is untested and may require some tweaking):

Template.something.helpers({
  sortedThings: function () {
    return Missatges
      .find({ topic: 'xxx' })
      .fetch()
      .sort(function (b, a) {
        var al = a.likes.length;
        var ad = a.dislikes.length;
        var bl = a.likes.length;
        var bd = a.dislikes.length;
        var d1 = a.date;
        var d2 = b.date;

        // compare by likes
        if (al > bl) return 1;
        if (al < bl) return -1;

        // compare by dislikes
        if (ad < bd) return 1;
        if (ad > bd) return -1;

        // compare by date
        if (d1 > d2) return 1;
        if (d1 < d2) return -1;

        // they are equal
        return 0;
      });
  },
});
David Weldon
  • 63,632
  • 11
  • 148
  • 146
  • It should be possible to have the custom sort function passed in the `sort` attribute of the second argument to `find()` itself once [this issue](https://github.com/meteor/meteor/issues/2730) is fully resolved (I intend to submit a PR soon). – MasterAM Jun 03 '16 at 12:32
  • Thank you David, finally, though, I opted for the solution presented on the link you provided me. I added 2 Number fields to the model: nLike and nUnlikes. It gets more handy even in other use cases I have – Vice Sallés Jun 06 '16 at 06:04