mongodb子文档中的分页子文档 [英] paging subdocument in mongodb subdocument

查看:172
本文介绍了mongodb子文档中的分页子文档的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在Mongodb中分页我的数据.我使用slice运算符,但无法分页数据.我希望进入我的行,但不能在此行分页.

I want to paging my data in Mongodb. I use slice operator but can not paging my data. I wish to bring my row but can not paging in this row.

我只想返回两行数据源.

I want to return only 2 rows of data source.

如何解决

我的查询:

db.getCollection('forms').find({
    "_id": ObjectId("557e8c93a6df1a22041e0879"),
    "Questions._id": ObjectId("557e8c9fa6df1a22041e087b")
}, {
    "Questions.$.DataSource": {
    "$slice": [0, 2]
    },
    "_id": 0,
    "Questions.DataSourceItemCount": 1
})

我的收藏数据:

/* 1 */
{
    "_id" : ObjectId("557e8c93a6df1a22041e0879"),
    "QuestionCount" : 2.0000000000000000,
    "Questions" : [ 
        {
            "_id" : ObjectId("557e8c9ba6df1a22041e087a"),
            "DataSource" : [],
            "DataSourceItemCount" : NumberLong(0)
        }, 
        {
            "_id" : ObjectId("557e8c9fa6df1a22041e087b"),
            "DataSource" : [ 
                {
                    "_id" : ObjectId("557e9428a6df1a198011fa55"),
                    "CreationDate" : ISODate("2015-06-15T09:00:24.485Z"),
                    "IsActive" : true,
                    "Text" : "sdf",
                    "Value" : "sdf"
                }, 
                {
                    "_id" : ObjectId("557e98e9a6df1a1a88da8b1d"),
                    "CreationDate" : ISODate("2015-06-15T09:20:41.027Z"),
                    "IsActive" : true,
                    "Text" : "das",
                    "Value" : "asdf"
                }, 
                {
                    "_id" : ObjectId("557e98eea6df1a1a88da8b1e"),
                    "CreationDate" : ISODate("2015-06-15T09:20:46.889Z"),
                    "IsActive" : true,
                    "Text" : "asdf",
                    "Value" : "asdf"
                }, 
                {
                    "_id" : ObjectId("557e98f2a6df1a1a88da8b1f"),
                    "CreationDate" : ISODate("2015-06-15T09:20:50.401Z"),
                    "IsActive" : true,
                    "Text" : "asd",
                    "Value" : "asd"
                }, 
                {
                    "_id" : ObjectId("557e98f5a6df1a1a88da8b20"),
                    "CreationDate" : ISODate("2015-06-15T09:20:53.639Z"),
                    "IsActive" : true,
                    "Text" : "asd",
                    "Value" : "asd"
                }
            ],
            "DataSourceItemCount" : NumberLong(5)
        }
    ],
    "Name" : "er"
}

推荐答案

尽管这可以通过一些实际的调整来完成,但是最好更改文档结构以将数组条目展平"到单个数组中.主要原因是由于

Though this is possible to do with some real wrangling you would be best off changing the document structure to "flatten" the array entries into a single array. The main reason for this is "updates" which are not atomically supported by MongoDB with respect to updating the "inner" array due to the current limitations of the positional $ operator.

无论如何,由于显而易见的原因,要处理它并不容易.

At any rate, it's not easy to deal with for the reasons that will become apparent.

对于当前结构,您可以这样处理:

For the present structure you approach it like this:

db.collection.aggregate([
    // Match the required document and `_id` is unique
    { "$match": {
        "_id":  ObjectId("557e8c93a6df1a22041e0879")
    }},

    // Unwind the outer array
    { "$unwind": "$Questions" },

    // Match the inner entry
    { "$match": {
        "Questions._id": ObjectId("557e8c9fa6df1a22041e087b"),
    }},

    // Unwind the inner array
    { "$unwind": "$Questions.DataSource" }

    // Find the first element
    { "$group": {
        "_id": {
            "_id": "$_id",
            "questionId": "$Questions._id"
       },
       "firstSource": { "$first": "$Questions.DataSource" },
       "sources": { "$push": "$Questions.DataSource" }
    }},

    // Unwind the sources again
    { "$unwind": "$sources" },

    // Compare the elements to keep
    { "$project": {
        "firstSource": 1,
        "sources": 1,
        "seen": { "$eq": [ "$firstSource._id", "$sources._id" ] }
    }},

    // Filter out anything "seen"
    { "$match": { "seen": true } },

    // Group back the elements you want
    { "$group": {
        "_id": "$_id",
        "firstSource": "$firstSource",
        "secondSource": { "$first": "$sources" }
    }}
])

因此,这将为您提供该内部数组的前两个元素".这是在聚合框架中实现$slice的基本过程,这是必需的 ,因为您不能以尝试的方式将标准投影与嵌套数组"一起使用.

So that is going to give you the "first two elements" of that inner array. It's the basic process for implementing $slice in the aggregation framework, which is required since you cannot use standard projection with a "nested array" in the way you are trying.

由于聚合框架不支持$slice,因此您可以看到进行分页"对于拔出"数组元素将是非常可怕且迭代"的操作.

Since $slice is not supported otherwise with the aggregation framework, you can see that doing "paging" would be a pretty horrible and "iterative" operation in order to "pluck" the array elements.

在这一点上,我可以建议将展平"到单个数组,但是存在相同的切片"问题,因为即使将"QuestionId"设为内部"数据的属性,它也具有相同的投影和选择问题为此,您需要使用相同的汇总方法.

I could at this point suggest "flattening" to a single array, but the same "slicing" problem applies because even if you made "QuestionId" a property of the "inner" data, it has the same projection an selection problems for which you need the same aggregation approach.

然后,对于您的数据(对于某些查询操作)来说,这种看似"的结构并不是很好,但是这完全取决于您的使用模式.这种结构适合这种类型的操作:

Then there is this "seemingly" not great structure for your data ( for some query operations ) but it all depends on your usage patterns. This structure suits this type of operation:

{
    "_id" : ObjectId("557e8c93a6df1a22041e0879"),
    "QuestionCount" : 2.0000000000000000,
    "Questions" : {
        "557e8c9ba6df1a22041e087a": {
            "DataSource" : [],
            "DataSourceItemCount" : NumberLong(0)
        }, 
        "557e8c9fa6df1a22041e087b": {
            "DataSource" : [ 
                {
                    "_id" : ObjectId("557e9428a6df1a198011fa55"),
                    "CreationDate" : ISODate("2015-06-15T09:00:24.485Z"),
                    "IsActive" : true,
                    "Text" : "sdf",
                    "Value" : "sdf"
                }, 
                {
                    "_id" : ObjectId("557e98e9a6df1a1a88da8b1d"),
                    "CreationDate" : ISODate("2015-06-15T09:20:41.027Z"),
                    "IsActive" : true,
                    "Text" : "das",
                    "Value" : "asdf"
                }
            ],
            "DataSourceItemCount" : NumberLong(5)
        }
    }
}

该方法在哪里起作用:

db.collection.find(
    { 
        "_id": ObjectId("557e8c93a6df1a22041e0879"),
        "Questions.557e8c9fa6df1a22041e087b": { "$exists": true }
    },
    { 
        "_id": 0,
        "Questions.557e8c9fa6df1a22041e087b.DataSource": { "$slice": [0, 2] },
        "Questions.557e8c9fa6df1a22041e087b.DataSourceItemCount": 1
    }
)

嵌套数组不适用于许多操作,尤其是更新操作,因为无法获取更新操作的内部"数组索引.位置$运算符将仅获取第一个"或外部"数组索引,而不能也"匹配内部数组索引.

Nested arrays are not great for many operations, particularly update operations since it is not possible to get the "inner" array index for update operations. The positional $ operator will only get the "first" or "outer" array index and cannot "also" match the inner array index.

使用像您这样的结构进行的更新涉及整个读取"文档,然后使用代码进行操作并回写.没有保证",文档在这些操作之间的集合中没有发生任何更改,除非处理不当,否则可能导致不一致.

Updates with a structure like you have involve "reading" the document as a whole and then manipulating in code and writing back. There is no "guarantee" that the document has not changed in the collection between those operations and it can lead to inconsistencies unless handled properly.

另一方面,所示的修订结构对于给定的查询类型效果很好,但是如果您需要跨外部"表示的内容进行动态搜索或汇总",则该结构可能会很糟糕".问题".

On the other hand, the revised structure as shown, works well for the type of query given, but may be "bad" if you need to dynamically search or "aggregate" across what you have represented as the "outer" "Questions".

MongoDB的数据结构非常依赖于如何使用它".因此,最好在钉牢"应用程序的最终数据结构设计之前,考虑所有使用模式.

Data structure with MongoDB is very subjective to "how you use it". So it is best to consider all of your usage patterns before "nailing down" a final data structure design for your application.

因此,您可以记录所提到的问题和解决方案,或者只是通过标准的位置"匹配来获取外部"元素,然后在客户端代码中仅进行切片".

So you can either take note of the problems and solutions as noted, or simply live with retrieving the "outer" element via the standard "positional" match and then just "slice" in your client code.

这是最适合您的应用程序"的问题.

It's all a matter of "what suits your application best".

这篇关于mongodb子文档中的分页子文档的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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