MongoDB 我们不知道对象中的键的对象中所有值的总和
MongoDB sum of all values in an object where we do not know the keys in the object
示例文档 1
{
"site": "xyz.com",
"Reg_NumReviews": {
"value1": "194",
"value53": "3,570"
},
"Reg_Score": {
"value1": "3.24",
"value53": "1.9"
}
}
修改后需要的文档
{
"site": "xyz.com",
"Reg_NumReviews": {
"value1": "194",
"value53": "3,570"
},
"Reg_Score": {
"value1": "3.24",
"value53": "1.9"
},
"Total_reviews" : "3764"
"Average_score" : 1.97
}
示例文档 2
{
"site": "werw.com",
"Reg_NumReviews": {
"value1": "194",
"value33": "2014",
"value5": "234"
},
"Reg_Score": {
"value1": "2.24",
"value33": "3.9",
"value33": "3",
}
}
修改后需要的文档
{
"site": "werw.com",
"Reg_NumReviews": {
"value1": "194",
"value33": "2014",
"value5": "234"
},
"Reg_Score": {
"value1": "2.24",
"value33": "3.9",
"value5": "3",
},
"Total_reviews" : "2442"
"Average_score" : "3.68"
}
我试过的代码是以下代码的变体。
db.SiteData.update({"site": "xyz.com" },
[ {"$set": { "Total_reviews" :
{"$sum" : {"$regex" : /Reg_NumReviews.\.*/} }}}],
{upsert:true})
如果用文字来形容的话:
- 找到站点与必要模式匹配的文档。
- 检查 Reg_NumReviews 是对象中的键。如果是,则开始设置操作。将所有键值对的值求和,赋值为Total_reviews.
- 进入下一个操作,稍微复杂一些。在 Reg_NumReviews 和 Reg_Scores 中找到匹配的键并将它们相乘。将所有这些值相加并除以 Total_reviews,分配为 Average_score.
编辑
澄清第3步
例如在文件二
效果为:
Average_score =
(
( Reg_NumReviews.value1 * RegScore.value1 ) +
( Reg_NumReviews.value33 * RegScore.value33 ) +
( Reg_NumReviews.value5 * RegScore.value5 )
) / Total_reviews
如果您使用的是 Mongo 版本 4.4+,您可以使用此更新,它使用 $objectToArray, then for each it sums them up accordingly, the reason we require v4.4 is due to the usage of $replaceAll 转换字段,用于从数字字符串中删除 ,
以允许Mongo 将其转换为数字。
如果您使用的是较小的 Mongo 版本,您仍然可以获得相同的结果,您只需使用不同的方法删除 ,
,例如使用 $split
,
作为分隔符,然后 $concat
重建字符串。
db.collection.updateMany(
{
"site": "xyz.com"
},
[
{
"$set": {
"Total_reviews": {
$sum: {
$map: {
input: {
$objectToArray: "$Reg_NumReviews"
},
as: "datum",
in: {
$toLong: {
$replaceAll: {
input: "$$datum.v",
find: ",",
replacement: ""
}
}
}
}
}
},
Average_score: {
$avg: {
$map: {
input: {
$objectToArray: "$Reg_Score"
},
as: "datum",
in: {
$toDouble: "$$datum.v"
}
}
}
}
}
}
])
Mongo Playground
---- 编辑 -----
假设 Reg_score
和 Reg_NumReviews
具有相同数量的键,您可以使用 $zip 来计算您的最后一个要求,如下所示:
db.collection.updateMany(
{
"site": "xyz.com"
},
[
{
$set: {
tmpReviews: {
$map: {
input: {
$objectToArray: "$Reg_NumReviews"
},
as: "datum",
in: {
$toLong: {
$replaceAll: {
input: "$$datum.v",
find: ",",
replacement: ""
}
}
}
}
},
tmpScores: {
$map: {
input: {
$objectToArray: "$Reg_Score"
},
as: "datum",
in: {
$toDouble: "$$datum.v"
}
}
}
}
},
{
"$set": {
"Total_reviews": {
$sum: "$tmpReviews"
},
Average_score: {
$avg: "$tmpScores"
},
New_complicated_field: {
$divide: [
{
$sum: {
$map: {
input: {
$zip: {
inputs: [
"$tmpReviews",
"$tmpScores"
]
}
},
as: "zipped",
in: {
$multiply: [
{
$arrayElemAt: [
"$$zipped",
0
]
},
{
$arrayElemAt: [
"$$zipped",
1
]
}
]
}
}
}
},
{
$sum: "$tmpReviews"
}
]
}
}
},
{
$unset: {
tmpReviews: 1,
tmpScores: 1
}
}
])
示例文档 1
{
"site": "xyz.com",
"Reg_NumReviews": {
"value1": "194",
"value53": "3,570"
},
"Reg_Score": {
"value1": "3.24",
"value53": "1.9"
}
}
修改后需要的文档
{
"site": "xyz.com",
"Reg_NumReviews": {
"value1": "194",
"value53": "3,570"
},
"Reg_Score": {
"value1": "3.24",
"value53": "1.9"
},
"Total_reviews" : "3764"
"Average_score" : 1.97
}
示例文档 2
{
"site": "werw.com",
"Reg_NumReviews": {
"value1": "194",
"value33": "2014",
"value5": "234"
},
"Reg_Score": {
"value1": "2.24",
"value33": "3.9",
"value33": "3",
}
}
修改后需要的文档
{
"site": "werw.com",
"Reg_NumReviews": {
"value1": "194",
"value33": "2014",
"value5": "234"
},
"Reg_Score": {
"value1": "2.24",
"value33": "3.9",
"value5": "3",
},
"Total_reviews" : "2442"
"Average_score" : "3.68"
}
我试过的代码是以下代码的变体。
db.SiteData.update({"site": "xyz.com" },
[ {"$set": { "Total_reviews" :
{"$sum" : {"$regex" : /Reg_NumReviews.\.*/} }}}],
{upsert:true})
如果用文字来形容的话:
- 找到站点与必要模式匹配的文档。
- 检查 Reg_NumReviews 是对象中的键。如果是,则开始设置操作。将所有键值对的值求和,赋值为Total_reviews.
- 进入下一个操作,稍微复杂一些。在 Reg_NumReviews 和 Reg_Scores 中找到匹配的键并将它们相乘。将所有这些值相加并除以 Total_reviews,分配为 Average_score.
编辑 澄清第3步 例如在文件二
效果为:
Average_score =
(
( Reg_NumReviews.value1 * RegScore.value1 ) +
( Reg_NumReviews.value33 * RegScore.value33 ) +
( Reg_NumReviews.value5 * RegScore.value5 )
) / Total_reviews
如果您使用的是 Mongo 版本 4.4+,您可以使用此更新,它使用 $objectToArray, then for each it sums them up accordingly, the reason we require v4.4 is due to the usage of $replaceAll 转换字段,用于从数字字符串中删除 ,
以允许Mongo 将其转换为数字。
如果您使用的是较小的 Mongo 版本,您仍然可以获得相同的结果,您只需使用不同的方法删除 ,
,例如使用 $split
,
作为分隔符,然后 $concat
重建字符串。
db.collection.updateMany(
{
"site": "xyz.com"
},
[
{
"$set": {
"Total_reviews": {
$sum: {
$map: {
input: {
$objectToArray: "$Reg_NumReviews"
},
as: "datum",
in: {
$toLong: {
$replaceAll: {
input: "$$datum.v",
find: ",",
replacement: ""
}
}
}
}
}
},
Average_score: {
$avg: {
$map: {
input: {
$objectToArray: "$Reg_Score"
},
as: "datum",
in: {
$toDouble: "$$datum.v"
}
}
}
}
}
}
])
Mongo Playground ---- 编辑 -----
假设 Reg_score
和 Reg_NumReviews
具有相同数量的键,您可以使用 $zip 来计算您的最后一个要求,如下所示:
db.collection.updateMany(
{
"site": "xyz.com"
},
[
{
$set: {
tmpReviews: {
$map: {
input: {
$objectToArray: "$Reg_NumReviews"
},
as: "datum",
in: {
$toLong: {
$replaceAll: {
input: "$$datum.v",
find: ",",
replacement: ""
}
}
}
}
},
tmpScores: {
$map: {
input: {
$objectToArray: "$Reg_Score"
},
as: "datum",
in: {
$toDouble: "$$datum.v"
}
}
}
}
},
{
"$set": {
"Total_reviews": {
$sum: "$tmpReviews"
},
Average_score: {
$avg: "$tmpScores"
},
New_complicated_field: {
$divide: [
{
$sum: {
$map: {
input: {
$zip: {
inputs: [
"$tmpReviews",
"$tmpScores"
]
}
},
as: "zipped",
in: {
$multiply: [
{
$arrayElemAt: [
"$$zipped",
0
]
},
{
$arrayElemAt: [
"$$zipped",
1
]
}
]
}
}
}
},
{
$sum: "$tmpReviews"
}
]
}
}
},
{
$unset: {
tmpReviews: 1,
tmpScores: 1
}
}
])