Search code examples
mongodbmeteorminimongo

Publish cursor with simplified array data


I need to publish a simplified version of posts to users. Each post includes a 'likes' array which includes all the users who liked/disliked that post, e.g:

[
    { 
        _id: user_who_liked, 
        liked: 1 // or -1 for disliked 
    }, 
    ..
]

I'm trying to send a simplified version to the user who subscribes an array which just includes his/her like(s):

Meteor.publish('posts', function (cat) {
  var _self = this;
  return Songs.find({ category: cat, postedAt: { $gte: Date.now() - 3600000 } }).forEach(function (post, index) {
    if (_self.userId === post.likes[index]._id) {
      // INCLUDE
    } else
      // REMOVE

    return post;
  })
});

I know I could change the structure, including the 'likes' data within each user, but the posts are usually designed to be short-lived, to it's better to keep that data within each post.


Solution

  • You need to use this particular syntax to find posts having a likes field containing an array that contains at least one embedded document that contains the field by with the value this.userId.

    Meteor.publish("posts", function (cat) {
      return Songs.find({
        category: cat,
        postedAt: { $gte: Date.now() - 3600000 },
        "likes._id":this.userId
      },{
        fields:{
          likes:0
        }
      });
    });
    

    http://docs.mongodb.org/manual/tutorial/query-documents/#match-an-array-element

    EDIT : answer was previously using $elemMatch which is unnecessary because we only need to filter on one field.