从大量记录的minimongo查询挂起浏览器 [英] Query from minimongo of large number of records stucks and hangs browser

查看:109
本文介绍了从大量记录的minimongo查询挂起浏览器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在角流星中为管理员建立一个页面.

I am building a page for admin in angular-meteor.

我已经发布了来自集合中的所有记录:"帖子",并已对前端的所有记录进行了订阅.

I have published all the records from a collection: "posts" and have taken the subscription of all the records on front end.

$meteor.subscribe('posts');

在控制器中,如果我从minimongo中选择所有记录的游标,则它的工作原理如下:

In the controller, if I select the cursors of all records from minimongo it works fine like:

$scope.posts = $meteor.collection(Posts);

但是我想显示分页,因此,我希望每次只能记录有限的内容,例如:

But I want to display pagination, so for that I want limited records at a time like:

$scope.posts = $meteor.collection(function(){

        return Posts.find(

            {}, 
            {
                sort:   {'cDate.timestamp': -1},
                limit:  10
            }
        );
    });

它在minimongo中卡住了查询.浏览器挂起.

It stucks with the query in minimongo. And the browser hangs.

"帖子"集合仅包含500条记录.当我有200条记录时,它运行良好.

"posts" collection contains only 500 records. It was working fine when I had 200 records.

任何人都可以给我一个想法,我的代码和概念有什么问题吗?

Can anyone give me an idea whats wrong with my code and concepts?

好吧!当我在查询中评论 $ sort 行时,效果很好:

Okay! It worked fine when I commented the $sort line from query like this:

$scope.posts = $meteor.collection(function(){

            return Posts.find(

                {}, 
                {
                    //sort:   {'cDate.timestamp': -1},
                    limit:  10
                }
            );
        });

但是我需要对记录进行排序.那我现在该怎么办?

But I need to sort the records. So what should I do now?

还尝试将索引添加到sort属性中,如下所示:

Also tried adding index to the sort attribute like this:

db.Posts.ensureIndex({"cDate.timestamp": 1})

还是同样的问题.

推荐答案

将发布更改为接受这样的名为pageNumber的参数

Change your publication to accept a parameter called pageNumber like this

Meteor.publish('posts', function (pageNumber) {
   var numberOfRecordsPerPage = 10;
   var skipRecords = numberOfRecordsPerPage * (pageNumber - 1);
   return Post.find({
        "user_id": user_id
   }, {
        sort: { 'cDate.timestamp': -1 }
        skip: skipRecords, 
        limit: numberOfRecordsPerPage
   });
});

在客户端,我与角流星的合作不多.您可以使用this.pageNumber$scope.pageNumber在当前作用域下创建pageNumber属性.单击分页页面时,请更新此pageNumber变量.每当更改此变量时,请使用当前页码进行订阅.

On client side, I didn't work with angular-meteor much. You can create a pageNumber property under your current scope using this.pageNumber or $scope.pageNumber. Update this pageNumber variable whenever your pagination page is clicked. Whenever this variable is changed, subscribe using the current page number.

如果它使用标准的blaze模板,则可以使用autorun中的反应式var或session var来实现,就像这样. 在模板html中:

If it is using standard blaze template, I would do it using a reactive var or session var in an autorun like this. In template html:

<template name="postsTemplate">
     <ul>
         <!-- you would want to do this list based on total number of records -->
         <li class="pagination" data-value="1">1</li>
         <li class="pagination" data-value="2">2</li>
         <li class="pagination" data-value="3">3</li>
     </ul>
</template>

在模板js中:

Template.postsTemplate.created = function () {
    var template = this;
    Session.setDefault('paginationPage', 1);
    template.autorun(function () {
       var pageNumber = Session.get('paginationPage');
       Meteor.subscribe('posts', pageNumber);
    });
}

Template.postsTemplate.events(function () {
    'click .pagination': function (ev, template) {
         var target = $(ev.target);
         var pageNumber = target.attr('data-value');
         Session.set('paginationPage', pageNumber);
     }
});

这样,您在客户端上的任何时间点最多将有10条记录,因此不会使浏览器崩溃.您可能还想使用以下类似方式限制发送给客户端的字段

This way, you will have a maximum of 10 records at any point in time on the client, so it will not crash the browser. You might also want to limit the fields that you send to client using something like this

Meteor.publish('posts', function (pageNumber) {
   var numberOfRecordsPerPage = 10;
   var skipRecords = numberOfRecordsPerPage * (pageNumber - 1);
   return Post.find({
        "user_id": user_id
   }, {
        sort: { 'cDate.timestamp': -1 }
        skip: skipRecords, 
        limit: numberOfRecordsPerPage,
        fields: {'message': 1, 'createdBy': 1, 'createdDate': 1 } //The properties inside each document of the posts collection.
   });
});

最后,您将需要客户端上的帖子集合中的记录总数,以显示分页链接.您可以使用其他出版物并使用官方文档此处

And finally you will need the total number of records in posts collection on client side, to show the pagination links. You can do it using a different publication and using the observeChanges concept as mentioned in the official documentation here

// server: publish the current size of a collection
Meteor.publish("posts-count", function () {
  var self = this;
  var count = 0;
  var initializing = true;

  // observeChanges only returns after the initial `added` callbacks
  // have run. Until then, we don't want to send a lot of
  // `self.changed()` messages - hence tracking the
  // `initializing` state.
  var handle = Posts.find({}).observeChanges({
    added: function (id) {
      count++;
      if (!initializing)
        self.changed("postsCount", 1, {count: count});
    },
    removed: function (id) {
      count--;
      self.changed("postsCount", 1, {count: count});
    }
    // don't care about changed
  });

  // Instead, we'll send one `self.added()` message right after
  // observeChanges has returned, and mark the subscription as
  // ready.
  initializing = false;
  self.added("postsCount", 1, {count: count});
  self.ready();

  // Stop observing the cursor when client unsubs.
  // Stopping a subscription automatically takes
  // care of sending the client any removed messages.
  self.onStop(function () {
    handle.stop();
  });
});

// client: declare collection to hold count object
PostsCount = new Mongo.Collection("postsCount");

// to get the total number of records and total number of pages
var doc = PostsCount.findOne(); //since we only publish one record with "d == 1", we don't need use query selectors
var count = 0, totalPages = 0;

if (doc) {
    count = doc.count;
    totalPages = Math.ceil(count / 10); //since page number cannot be floating point numbers..
}

希望这会有所帮助.

这篇关于从大量记录的minimongo查询挂起浏览器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆