JoeTidee
JoeTidee

Reputation: 26054

Reducing the number of Mongo records send to browser by Meteor?

I have a Mongo collection of items (items). I have another collection of privileges that are associated to the items (item_ownership), one such privilege stores the ID of the user that owns an item (owner_id). I want to get all the items that a user owns and publish them. So, in theory, I want to first select the item_id's from the 'item_ownership' collection that can then be inserted into a query on the 'items' collection to filter it. This filtered result set will be published to the browser:

Items = new Mongo.Collection("items");
ItemOwnership = new Mongo.Collection("item_ownership");

Meteor.publish('items_pub', function() {

        var itemOwnershipColl = ItemOwnership.find(
            {
                owner_id: Meteor.userId()
            },
            {
                fields: { item_id: 1 }
            }
        );

        // Compile list of items to return.
        var item_id_array = [];
        itemOwnershipColl.forEach(function (record) {
            item_id_array[item_id_array.length] = record.item_id;
        });

        return Items.find(
            {
                item_id: { $in: item_id_array }
            },
            {
                sort: {
                    item_order: 1
                }
            }
        );
});

Is this the best way to go about doing this?

Upvotes: 0

Views: 44

Answers (2)

Michel Floyd
Michel Floyd

Reputation: 20226

The reywood:publish-composite package is excellent for dealing with such relationships in your data model.

Upvotes: 2

David Weldon
David Weldon

Reputation: 64312

If I understand your schema correctly, it seems like your join is almost correct. Here's one way to write it:

Meteor.publish('items_pub', function() {
  var selector = {owner_id: this.userId};
  var items = ItemOwnership.find(selector, {fields: {item_id: 1}}).fetch();
  var itemIds = _.pluck(items, '_id');
  return Items.find({_id: {$in: itemIds}});
});

It does basically the same thing as your code with a few shortcuts an corrections:

  • You were missing a fetch after the initial find. Without it you won't have access to the documents.
  • _.pluck is an easier way to extract the ids into an array.
  • Sorting in a publish isn't useful unless it's combined with limit or skip. See common mistakes.
  • I'm assuming you mean to search for _id and not item_id in the last find.

It's also worth noting that this kind of join collection (ItemOwnership) is usually unnecessary when using mongodb. A better solution may be to store an array of items on the user, or an array of users on the item.

Upvotes: 1

Related Questions