递归发布 - Angular-meteor

Recursive Publishing - Angular-meteor

我想加载一个主题、它的 25 条评论和每条评论最多 5 条子评论,对每个评论重复递归 comment/sub-comment 直到找到所有相关评论。

我目前正在使用 angular 指令递归订阅并在评论有 children 时添加到本地集合。它工作得很好,但在加载最初的 25 条评论和加载它们的 children,然后它们的 children 等等之间存在一些延迟(可以预料)。

如果一次只加载一个页面,这个问题不是问题。当使用无限滚动并增加最初的 25 条评论限制时,这会成为一个问题。当子评论消失并再次加载后重新出现时,它会导致页面上下跳动。

我想知道如何在发送给本地客户端之前递归地查找所有评论,这样我就不需要为每个主题进行多次往返。

我在 ck-gaming.com

加载了一个演示

如果您滚动到底部,它将加载更多内容,并且您会看到它在子评论重新加载到页面时跳到整个页面。

我能想到的两个选项是在加载页面之前使用解析等待所有集合,或者使用递归发布首先获取它们。

想法?想法?

好的,我的第一次尝试,如果可能的话,我想谈谈一些想法。

对于发布,我决定使用 publish-composite 以便更容易地从同一个集合中发布。

我写的出版物:

Meteor.publishComposite('oneDiscussion', function (slug, options) {

var query = {};
query.find = function () {
    return Discussions.find({ slug: slug }, { limit: 1 });
};

var mainChildQuery = Comments.find({ slug: slug }, { limit: 1 });

query.children = [];
query.children[0] = {};
query.children[0].find = function (discussion) {
    return mainChildQuery;
};
query.children[0].children = [];
query.children[0].children[0] = {};
query.children[0].children[0].find = function (comment) {
    return Meteor.users.find({ _id: comment.author.id }, { limit: 1, fields: { profile: 1, roles: 1, createdAt: 1, username: 1 } });
};
query.children[0].children[1] = {};
query.children[0].children[1].find = function (parent) {
    Counts.publish(this, 'numberOfComments', Comments.find(
        { parent_id: parent._id }
        ), { noReady: true });
    console.log(options)
    return Comments.find({ parent_id: parent._id }, options);
};

//  var parentQuery = Comments.find({ slug: slug });
var parent = mainChildQuery.fetch();
var children = Comments.find({ parent_id: parent[0]._id }, { limit: 25 }).fetch();

var childrenIds = _.pluck(children, '_id');


var getChildren = function (children_ids, thisParent) {

    var i = 0;
    thisParent.children = [];

    var recursive = function getEm(children, parent) {
        _.each(children, function (id) {

            //              parent.children[i] = new Children(id);
            var query = Comments.find({ parent_id: id }, { limit: 5, sort: { date: -1 } });
            parent.children[i] = {
                find: function () {
                    return Comments.find({ parent_id: id }, { limit: 5, sort: { date: -1 } });
                }
            };


            var children1 = query.fetch();
            var newChildrenIds = _.pluck(children1, '_id');
            i++;
            if (newChildrenIds.length > 0) {
                getEm(newChildrenIds, parent);
            }
        });
    }

    recursive(children_ids, thisParent);

};

getChildren(childrenIds, query.children[0].children[1]);
return query;

});

到目前为止似乎工作正常,但 运行 它在我的桌面上的性能不如我想象的那么好。我会部署它,看看是否有在线差异。我会在回家时更新并且可以更新实时站点。如果有人能发现我写的东西有问题,将不胜感激。

我想出了我认为最好的解决方案。我改进了上面的功能,到目前为止我真的很喜欢结果。

这里是发布函数:

Meteor.publishComposite('comments', function (item_id, options) {
    /**
     * TODO: Add query to find a user for each comment.
     */
    /**
     * Start building our query.
     * Add the latest 25 (depending on options) child comments of the viewed item
     * to the query.
     */
    var query = {
        find: function () {
            return Comments.find({ parent_id: item_id }, options);
        }
    };
    // Query the database for the first 25? comments, we'll need their _id's
    var mainChildren = Comments.find({ parent_id: item_id }, options).fetch();
    // pluck the id's from the initial comments
    var mainChildrenIds = _.pluck(mainChildren, '_id');

    /**
     * Builds the remaining query based on the id's plucked from the children
     *  above.
     * @param childrens_id The id's we just plucked from the above query
     * @param thisParent This is the parent query
     */
    var getChildren = function (children_ids, parentQuery) {
        // initiate i to 0
        var i = 0;
        // add a child array to the current parent query.
        parentQuery.children = [];
        var recursive = function getem(children, parent) {
            _.each(children, function (id) {
                var query = Comments.find({ parent_id: id }, { limit: 5, sort: { date: 1 } });
                parent.children[i] = {
                    find: function () {
                        return query;
                    }
                };
                var children1 = query.fetch();
                var newChildrenIds = _.pluck(children1, '_id');
                i++;
                if (newChildrenIds.length > 0) {
                    getem(newChildrenIds, parent);
                }
            });
        };
        // recursively build the query if there are children found.
        recursive(children_ids, parentQuery);
    };
    // initiate the query build function
    getChildren(mainChildrenIds, query);
    return query;
});

我创建了一个示例应用程序,您可以在 GitHub here

你可以在 meteorpad 运行 上查看 here

它的作用

该函数所做的就是构建 publishComposite 查询,递归循环遍历 children 个 ID,只要有 children 个 ID。当没有更多 children 时它停止。

使用它

您想要一组具有 parent_id 字段的评论(或您嵌套的任何内容)。此字段将填充 parent post Id,parent 项目 ID(如果说用 reviews/comments 建立商店)。 parent post id 当然是您正在评论的评论或 post。有关详细信息,请参阅示例。