考虑以下测试结果集合:
[{
_id: ObjectId(...),
name: "Test1",
acts: [
{
name: "act1",
tests: [
{name: "test1", result: true},
{name: "test2", result: true}]
}]
},
{
_id: ObjectId(...),
name: "Test2",
acts: [
{
name: "act1",
tests: [
{name: "test1", result: true},
{name: "test2", result: false}]
},
{
name: "act2",
tests: [
{name: "test3", result: true}]
}]
}]
我正在尝试使用聚合来创建一个包含所有测试结果之和的计算字段,我想要这样的东西:
[{
_id: ObjectId(...),
name: "Test1",
result: true, //new aggregated value
acts: [
{
name: "act1",
result: true, //new aggregated value
tests: [
{name: "test1", result: true},
{name: "test2", result: true}]
}]
},
{
_id: ObjectId(...),
name: "Test2",
result: false, //new aggregated value
acts: [
{
name: "act1",
result: false, //new aggregated value
tests: [
{name: "test1", result: true},
{name: "test2", result: false}]
},
{
name: "act2",
result: true, //new aggregated value
tests: [
{name: "test3", result: true}]
}]
}]
我试过使用聚合和$ unwind,$ project和$ group:
aggregate([
{$unwind: "$acts"},
{$unwind: "$acts.tests"},
{$project: {name: 1, acts: 1, failed: {$cond: {if: {$eq: ["$acts.tests.test", "true" ]}, then: 0, else: 1}}}},
{$group: {_id: "$_id", failedCount: {$sum: "$failed"}, acts: {$push: "$acts.tests"}}}
])
但是我无法使它撤消$ unwind操作,只能得到与原始数据不同的数据结构。是否有可能使结果看起来像原始集合,但具有新的聚合值?
/垃圾邮件
如何处理此问题有一个特殊的技巧,但是首先,如果您拥有可用的MongoDB 2.6或更高版本,则实际上可以在不使用的情况下完成所需的操作$unwind
。如果要处理大量文档,这对性能非常方便。
此处的关键运算符是$map
处理适当位置的数组的$allElementsTrue
运算符,而运算符将评估您的“结果”字段。这里使用“ map”可以对内部“ tests”数组进行测试,以查看其中的“ result”字段都满足真实条件的位置。在外部数组的情况下,可以根据需要将此“结果”放入那些文档中,当然,对文档的完整评估遵循相同的规则:
db.test.aggregate([
{ "$project": {
"name": 1,
"result": {
"$allElementsTrue": {
"$map": {
"input": "$acts",
"as": "act",
"in": {
"$allElementsTrue": {
"$map": {
"input": "$$act.tests",
"as": "test",
"in": "$$test.result"
}
}
}
}
}
},
"acts": {
"$map": {
"input": "$acts",
"as": "act",
"in": {
"name": "$$act.name",
"result": {
"$allElementsTrue": {
"$map": {
"input": "$$act.tests",
"as": "test",
"in": "$$test.result"
}
}
},
"tests": "$$act.tests"
}
}
}
}}
])
在早期版本中执行此操作的方法要求您$group
分两步进行操作,以便在再次对那些“结果”字段进行测试时“重建”阵列。此处的另一个区别是使用了$min
运算符,因为它false
被认为是比true
“ allElements”概念小的值,并且其计算结果相同:
db.test.aggregate([
{ "$unwind": "$acts" },
{ "$unwind": "$acts.tests" },
{ "$group": {
"_id": {
"_id": "$_id",
"name": "$name",
"actName": "$acts.name"
},
"result": { "$min": "$acts.tests.result" },
"tests": {
"$push": {
"name": "$acts.tests.name",
"result": "$acts.tests.result"
}
}
}},
{ "$group": {
"_id": "$_id._id",
"name": { "$first": "$_id.name" },
"result": { "$min": "$result" },
"acts": {
"$push": {
"name": "$_id.actName",
"result": "$result",
"tests": "$tests"
}
}
}}
])
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句