获取子文档元素在数组中的每个索引的计数并更新子文档键 - 数组中的子文档(IN MONGODB)

时间:2014-02-28 07:10:16

标签: arrays mongodb subdocument

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

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

{
    "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子目录,其中元素计数为3,而第3个索引在Qty子目录中的元素数为1。

如果我想更新子文件密钥,比如,我想将数量从“10月12日”更新为“2013年12月10日”,那怎么可能?

提前致谢,尽快寻找答复..

1 个答案:

答案 0 :(得分:0)

首先,您实际上是在询问两个问题,"如何计算Qty下的项目?&#34 ; "如何更改名称?" 。虽然通常不相关,但我会将它们视为同样的事情。

您需要做的是更改您的架构,这样做我会允许您获取商品数量,我会鼓励您更改那些字段名称也是如此。具体来说,您需要这样的架构:

"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 },
        ]
    },

所有血腥细节都在my answer here的类似问题中。但问题基本上是,当你以你的方式使用子文档时,你破坏了对此进行任何有意义的查询操作的机会,为了得到每个元素你必须< / strong>指定到达那里的完整路径。

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

此外,相关,请将您的日期更改为日期和字符串。用于MongoDB内部比较的字符串不好。将它们设置为正确的BSON日期(注意我将它们剪切到一天的开始),您可以比较,查询范围并执行有用的操作。您的应用程序代码将很高兴,因为驱动程序将返回真实日期对象,而不是您必须操纵的东西&#34;两种方式&#34;。

所以曾经你已经阅读,理解并实施了这一点,直到计算:

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为每个EventCode的{​​{1}}中的项目获得 Type Qty最低。

当前架构 ,而无需在代码中加载和遍历每个文档。

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

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 } }}
)

您需要为每个项目执行此操作。

因此,您要么计算出架构转换,要么以其他方式进行批次工作,以便更改密钥。对于我自己,我会正确,只做一次,所以我以后不会遇到下一个问题。