David Panart
David Panart

Reputation: 656

How to handle "relations" with MongoDB / Meteor

I'm still on my Meteor.js app, and w'd like to show on my page all the posts from th current user's friends.

For the moment, I simply show every single post like this :

talkthreads: function(){
  return Posts.find({parent: null},{sort: {date: -1}});
}

But I'd like to do something as simple / efficient as possible to filter them and only have the one from the user's friends.

Something like that :

talkthreads: function(){
        return Posts.find({parent: null, owner: [match one of my friend id]}, {sort: {date: -1}});
    }

As I would do with SQL.

The other point is that I currently publish my posts collection to all client. But as it is aimed to grow with the time, I don't want to publish ALL the posts to each clients.

How can I only publish and subscribe to posts owned by me or my friends, and in a limited number : I don't want to load more than the 15 last posts at a time. And when I click a a button, I load 15 more (like when on FB, when you scroll at the bottom of the page, it automaticcaly append older posts).

Thanks you for your help.

Upvotes: 2

Views: 399

Answers (2)

David Weldon
David Weldon

Reputation: 64342

What you are asking for is a client-side join. Assuming Meteor.user().profile.friends is an array of user ids, something like this should work in your helper:

talkthreads: function() {
  // select owners who are friends of the current user
  // see the publish example if you want to include your own posts
  var owners = Meteor.user().profile.friends || [];

  var selector = {
    parent: null,
    owner: {$in: owners}
  };

  return Posts.find(selector, {sort: {date: -1}});
}

The second half of your question is about pagination. This is probably best asked as a separate question, but here's an idea of how to set up the publisher:

var POSTS_PER_PAGE = 15;

Meteor.publish('paginatedPosts', function(pageNumber) {
  // fetch the current user because Meteor.user() isn't available here
  var user = Meteor.findOne(this.userId);

  // get an array of user ids for the user's friends
  var owners = user.profile.friends || [];

  // also add the current userId to the list of owners
  owners.push(this.userId);

  var selector = {
    parent: null,
    owner: {$in: owners}
  };

  // publish a limited set of posts based on the current page
  var options = {
    limit: POSTS_PER_PAGE * pageNumber,
    sort: {date: -1}
  };

  return Posts.find(selector, options);
});

On the client you'll need to keep track of the current page (start with 1 and increment every time he/she clicks a "load more" button) and activate the subscription whenever the page number changes. For example:

Tracker.autorun(function() {
  var pageNumber = Session.get('currentPage') || 1;
  Meteor.subscribe('paginatedPosts', pageNumber);
});

Of course that could be a template autorun, or a global, or in your router, depending on what makes sense for your app.

Upvotes: 2

Tim C
Tim C

Reputation: 1934

I assume your user has an array of friends _id's which you can use to query with. In this case you're looking to do a query like this:

 Posts.find({parent: null, owner: Users.find({_id: user_is}, {friends: 1, _id: 0})}, {sort: {date: -1}});

Basically with Mongo you can nest your searches, like so, so get the data you need.

Upvotes: 1

Related Questions