获取数组中每个索引的子文档元素计数并更新子文档键 - 数组中的子文档(IN MONGODB)
Posted
技术标签:
【中文标题】获取数组中每个索引的子文档元素计数并更新子文档键 - 数组中的子文档(IN MONGODB)【英文标题】:Getting subdocument element's count per index inside an array and updating the subdocument key - subdocument in array(IN MONGODB) 【发布时间】:2014-04-01 01:35:10 【问题描述】:如何获取数组中子文档元素的计数以及如何在 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 子文档,该子文档的元素计数为 3,而第 3 个索引在 Qty 子文档中的元素计数为 1。
如果我想更新 subdoc 键,例如,我想将 Qty 中的日期从“10-Dec”更新为“10-Dec-2013”,怎么可能?
提前致谢,期待尽快回复..
【问题讨论】:
有人(还不是我)刚刚对你投了反对票,因为你没有像网站要求你做的那样格式化你的数据块。 DONT SHOUT 一切都以粗体显示。未来的注意事项。但是现在你可能会得到一些帮助。 现在。您的问题是(澄清)您想要更新 Qty 下子文档中的值。对吗? 感谢 Neil 为我提供未来注意事项的建议。我不想更新 Qty 中的 value 字段,我想更新存储在数组 TktDetail 中的 Qty 中的键名,例如:如果它是“10-Dec”,那么我想将其更新为“10 -2013 年 12 月”。 我也想知道,我怎样才能得到每个索引数量内的元素数量,第 0 个索引的数量有 3 作为计数,第 3 个索引的数量有 1 作为计数,以dis方式? 【参考方案1】:所以这里的第一件事是您实际上问了 两个 问题,即 “我如何计算 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 ,
]
,
所有血淋淋的细节都在my answer here 中,用于类似的问题。但问题基本上是,当你以你拥有的方式使用 子文档 时,你正在破坏你对它进行任何有意义的查询操作的机会,因为你必须 指定到达那里的完整路径。
answer 有更多细节,但情况是你真的想要一个数组。权衡一下,更新有点困难,特别是考虑到您有 嵌套数组,但它更容易添加并且更更容易查询。
此外,相关的,将您的日期更改为日期和不是字符串。字符串对于 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
])
这样我们就可以通过Type
获得Qty
中每个EventCode
中的项目的count 个,Qty
从高到低排序。
如果不加载和遍历代码中的每个文档,在您当前的架构上不可能。
原来如此。现在,如果您想 忽略 并只是更改 sub-document 键名,那么您需要删除键和基础文档并替换为新的键名,使用更新:
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
)
您需要为您拥有的每个项目执行此操作。
因此,您要么进行架构转换,要么进行 大量 工作以更改密钥。对我自己来说,我会正确地做,并且只做一次,这样我以后就不会遇到下一个问题了。
【讨论】:
我非常感谢您的回答,但是您要求我更改集合架构的第一个解决方案,在将来使用 $(Positional operator) 更新时会产生问题,因为它不是支持超过 1 级,数量将在 2 级,这就是我将其“数量”视为子文档而不是嵌套数组的原因。 Second 是一个已知的解决方案,我不能使用它,因为我想在不知道键名的情况下遍历 Qty 并更新它。 @SurajMishra 我很清楚位置更新的问题,因此我说这可能有些困难但并非不可能。如果有的话,应该在这个结构中被视为子文档的唯一项目是TktDetail
部分,这使得其他一些操作更加困难,但删除了位置更新问题。这是最少的路径问题,因此是最好的地方。即使您知道您必须使用 $set 和 $unset 做什么,也没有没有其他方法。如果您需要更好地解释更改后的结构,我可以这样做。以上是关于获取数组中每个索引的子文档元素计数并更新子文档键 - 数组中的子文档(IN MONGODB)的主要内容,如果未能解决你的问题,请参考以下文章