【问题标题】:Subdocuments pagination in MongooseMongoose中的子文档分页
【发布时间】:2013-05-21 02:44:45
【问题描述】:

我使用的是 Mongoose 3.6,我的(简化的)架构看起来像这样

var commentSchema = new Schema({
    created: Date  
});

var userSchema = new Schema({
    comments    : [commentSchema],
});

我想对 cme​​ts 进行分页,这样如果我的用户有 25 个 cmets,页面将分为:

page 1: comments 15-24
page 2: comments 5-14
page 3: comments 0-4
page 4: empty
page 5: empty
...

这是我尝试过的

this.findById(user_id, {
        comments: {
            $slice: [-comment_page_index * comments_per_page, comments_per_page]
        }
    }, function(err, user) {
        //...
});

虽然起初这似乎可行,但我很失望地发现 $slice 运算符会在达到集合边界时切断给定的索引。

所以我得到的是

page 1: comments 15-24
page 2: comments 5-14
page 3: comments 0-9
page 4: comments 0-9
page 5: comments 0-9
...

这里更好的选择可能是结合sortskiplimit 函数,但是虽然我知道如何在常规集合中使用它们,但我必须知道如何将它们应用于子文档.有什么想法吗?

【问题讨论】:

  • 可能最好不要将所有 cmets 都嵌入到用户中 - 活跃用户会使文档无限增长,这对性能来说不是一个好主意。
  • 谢谢你的建议,我会考虑的。无论如何,我想知道是否存在一种对子文档进行分页的方法,而无需重构整个结构
  • 您可以使用聚合框架 - $unwind 子文档数组,然后使用 $sort 和 $limit。
  • 这似乎是要走的路。如果您想举个例子并将其放在答案中,我将不胜感激:)无论如何我都会自己尝试

标签: mongodb pagination mongoose


【解决方案1】:

如果它是查找全部或与显示相关的,分页将类似于下面的代码。代码只是一个例子:

findAll: async function (req, res) {
    var responseObj = {};
    try {
        var responseObj = {};
        var queryArray = [];
        var finalAnswer = [];

        var loggedinUser = mongoose.Types.ObjectId(req.user.id)
        var auser = await user.findOne({ _id: loggedinUser })
        var places = auser.placesUnderIt;
        for (i of places) {
             var singlePlaceId = mongoose.Types.ObjectId(i);
             var singlePlaceData = await place.findOne({ _id: singlePlaceId })
             var list = singlePlaceData.controlledStore;
                    for (k of list) {
                        finalAnswer.push(k);
                    }

                }
             queryArray.push({ _id: { $in: finalAnswer} });
        var query = {
                $and: queryArray
            }

        responseObj.count = await store.countDocuments(query);
        responseObj.data = await store.find(query)
            .populate('ownerId', ["firstName", "lastName", "phoneNumber", "email", "personalDetails"])
            .populate('businesses')
            .limit(parseInt(req.query.limit))
            .skip(parseInt(req.query.skip));

        var data = responseObj.data;
        return res.send(responseObj);
    } catch (err) {
        return res.send('Error');
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-16
    • 2020-10-23
    • 1970-01-01
    • 1970-01-01
    • 2017-05-20
    • 2017-09-17
    • 1970-01-01
    相关资源
    最近更新 更多