Search code examples
javascriptnode.jsmeteorpublish-subscribe

Meteor: publish dynamically requested range of items


I have huge collection of over 5000+ records. I want to be able to view records 10 at a time. How can I dynamically publish the data that way?

I've tried this so far:

My server.js file :

Meteor.methods({
    publishSongs : function (first, last) {
        Meteor.publish('adminSongs', function() {
            return Songs.find({}, {
                skip : first,
                limit : last,
                sort : {
                    date : -1
                }
            });
        });
    }
});

My client.jsfile :

Template.admin.events({
    'click #previous' : function() {
        updateSession(-10);
        publishSong();
    },
    'click #next' : function() {
        updateSession(10);
        publishSong();
    }
});

Template.admin.onCreated(function() {
    Session.setDefault('limit', {
        first : 0,
        last : 10
    });
    publishSong()
})

function publishSong() {
    Meteor.call(
        'publishSong',
        Session.get('limit').first,
        Session.get('limit').last
    );
}

function updateSession(value) {
    Session.set('limit', {
        first: Session.get('limit').first + value,
        last: Session.get('limit').last + value,
    });
}

The server is printing this error message:

Ignoring duplicate publish named 'adminSongs'

It seems like I'm using publications wrong and could use some guidance.


Solution

  • It doesn't look like you're never updating your Session.get('limit'). You'll need to update then you press next/previous otherwise you're always going to get the same records. You'll also need to change the way you're doing publications:

    Template.admin.events({
        'click #previous' : function() {
            updateSession(-10);
        },
        'click #next' : function() {
            updateSession(10);
        }
    });
    
    Template.admin.onCreated(function() {
        Session.setDefault('limit', {
            first : 0,
            last : 10
        });
        Template.instance().autorun( function() {
            Template.instance().subscribe('adminSongs', Session.get('limit').first, Session.get('limit').last);
        });
    });
    
    function updateSession(value) {
        Session.set('limit', {
            first: Session.get('limit').first + value,
            last: Session.get('limit').last + value,
        });
    }
    

    I'm assuming based on your code that you already have a helper defined to return the available songs. The code above makes it so that you have one subscription, and that subscription will update any time your session variable changes.

    Your server code will also need to be updated:

    Meteor.publish('adminSongs', function(first, last) {
        return Songs.find({}, {
            skip : first,
            limit : last,
            sort : {
                date : -1
            }
        });
    });
    

    Can be outside of a Meteor.method.