0

如何在数组中获取子文档元素的计数以及如何在 MongoDB 中更新子文档的键

例如,以下是存储在 mongodb 中的整个文档:

{
    "CompanyCode" : "SNBN",
    "EventCode" : "ET00008352",
    "EventName" : "Sunburn Presents Avicii India Tour",
    "TktDetail" : [ 
        {
            "Type" : "Category I",
            "Qty" : {
                "10-Dec" : {
                    "value" : 58
                },
                "11-Dec" : {
                   "value" : 83
                },
                "12-Dec" : {
                   "value" : 100
                } 
            }
        }, 
        {
            "Type" : "Category II",
            "Qty" : {
                "10-Dec" : {
                   "value" : 4
                },
                "11-Dec" : {
                    "value" : 7
                },
                "12-Dec" : {
                    "value" : 8
                }
            }
        }, 
        {
            "Type" : "PRICE LEVEL 1",
            "Qty" : {
                "11-Dec" : {
                    "value" : 2
                }
            }
        }, 
        {
            "Type" : "CatIV",
            "Qty" : {
                "18-Dec" : {
                    "value" : 20
                }
            }
        }
    ],
    "TransDate" : [ 
        "10-Dec-2013", 
        "11-Dec-2013", 
        "12-Dec-2013", 
    ],
    "VenueCode" : "SNBN",
    "VenueName" : "Sunburn",
    "_id" : ObjectId("52452db273b92012c41ad612")
}

这里 TktDetail 是一个数组,其中有一个包含多个元素的 Qty 子文档,我想知道如何获取每个索引 Qty 内的元素计数?

例如,TktDetail 数组的第 0 个索引包含 1 个 Qty subdoc,其元素计数为 3,而第 3 个索引在 Qty subdoc 中的元素计数为 1。

如果我想更新 subdoc 键,例如,我想将 Qty 中的日期从“10-Dec”更新为“10-Dec-2013”​​,这怎么可能?

提前谢谢,希望尽快回复。。

4

1 回答 1

0

所以这里的第一件事是你实际上问了两个问题,“我如何计算 下的项目Qty?” “我怎样才能改变名字?” . 现在虽然通常不相关,但我会将它们视为同一件事。

您需要做的是更改您的架构,这样做我将允许您获取项目的数量,并且我将鼓励您也更改这些字段名称。具体来说,您需要这样的架构:

"TktDetail" : [ 
    {
        "Type" : "Category I",
        "Qty" : [
            { "date": ISODate("2013-12-10T00:00:00.000Z") , "value" : 58  },
            { "date": ISODate("2013-12-11T00:00:00.000Z"), "value" : 83  },
            { "date": ISODate("2013-12-01T00:00:00.000Z"), "value" : 100 },
        ]
    },

所有血腥细节都在对类似问题的回答中。但问题基本上是,当您以您拥有的方式使用子文档时,您正在破坏对此进行任何有意义的查询操作的机会,因为要获取每个元素,您必须指定到达那里的完整路径。

这个答案有更多细节,但情况是你真的想要一个数组。权衡,更新有点困难,特别是考虑到你有嵌套数组,但它更容易添加并且容易查询。

此外,相关的,将您的日期更改为日期而不是字符串。字符串适合在 MongoDB 中进行比较。将它们设置为适当的 BSON 日期(注意我将它们剪辑到一天的开始),您可以比较、查询范围并做有用的事情。您的应用程序代码会很高兴,因为驱动程序将返回一个真实的日期对象,而不是您必须“双向”操作的东西。

因此,一旦您通读、理解并实现了这一点,就可以开始计算:

db.collection.aggregate([

    // Unwind the TktDetail array to de-normalize
    {"$unwind": "$TktDetail"},

    // Also Unwind the Qty array
    {"$unwind": "$Qty" },

    // Get some group information and count the entries
    {"$group": { 
        "_id": {
            "_id": "$_id,
            "EventCode": "$EventCode",
            "Type": "$TktDetail.Type"
        },
        "Qty": {"$sum": 1 }
    }},

    // Project nicely
    {"$project": { 
        "_id": 0,
        "EventCode": "$_id.EventCode",
        "Type: "$_id.Type",
        "Qty": 1,
    }},

    // Let's even sort it 
    {"$sort": { "EventCode": 1, "Qty" -1 }}

])

这样我们就可以按从最高到最低的顺序来计算Qty每个项目的数量。EventCodeTypeQty

如果不加载和遍历代码中的每个文档,这在您当前的架构上是不可能的。

所以有这种情况。现在,如果您想忽略这一点而只是更改子文档的键名,那么您需要使用更新删除键和基础文档并替换为新的键名:

db.collection.update(
    { EventCode: "ET00008352"},
    { $unset:{ "TktDetail.0.Qty.10-Dec": "" }}
)

db.collection.update(
    { EventCode: "ET00008352"},
    { $set:{ "TktDetail.0.Qty.10-Dec-2013": { value: 58 } }}
)

你需要为你拥有的件物品都这样做。

因此,您要么计算出该模式转换,要么无论如何都要进行大量工作以更改密钥。对我自己来说,我会做的很好,而且只做一次,所以我以后没有遇到下一个问题。

于 2014-02-28T08:08:12.360 回答