草庐IT

MongoDB - 聚合多行

coder 2023-11-06 原文

假设如下聚合查询:

Machine.aggregate(  [ { $match : {  $and: [  {"idc": req.query.idc }, {"customer":req.query.customer} ] } } ,{"$group":{_id: {"cluster":"$cluster","idc":"$idc","type":"$type"},"SumCores":{"$sum":"$cores"},"SumMemory": { "$sum":"$memory" }}}, { $sort : { idc : -1, cluster: 1 } } ]);

哪个返回:

[
{
    "_id": {
        "cluster": 1,
        "idc": "LH5",
        "type": "Virtual"
    },
    "SumCores": 112,
    "SumMemory": 384
},
{
    "_id": {
        "cluster": 1,
        "idc": "LH5",
        "type": "Physical"
    },
    "SumCores": 192,
    "SumMemory": 768
},
{
    "_id": {
        "cluster": 1,
        "idc": "LH8",
        "type": "Virtual"
    },
    "SumCores": 232,
    "SumMemory": 469
},
{
    "_id": {
        "cluster": 1,
        "idc": "LH8",
        "type": "Physical"
    },
    "SumCores": 256,
    "SumMemory": 1024
}
]

有没有办法更改聚合以检索所需的输出:

[
   {
    "_id": {
        "cluster": 1,
        "idc": "LH5"
    },
    "Virtual": {
        "SumCores": 112,
        "SumMemory": 384
    },
    "Physical": {
        "SumCores": 192,
        "SumMemory": 768
    }
},
{
    "_id": {
        "cluster": 1,
        "idc": "LH8"
    },
    "Virtual": {
        "SumCores": 232,
        "SumMemory": 469
    },
    "Physical": {
        "idc": "LH8",
        "type": "Physical"
    }
}
]

假设:

  • 每个 IDC/集群总会有一个物理和虚拟“对”

我很高兴收到以下解决方案:

a) 改变聚合查询 b) 接收现有数据并通过库和/或算法将其更改为这种格式

最佳答案

您已经在查询中做了所有正确的事情,因为您需要在您拥有的级别上 $group 以获得正确的总和。唯一剩下的就是将它们整合在一起。

就我个人而言,我会坚持使用数组中的“对”作为最终输出:

Machine.aggregate([ 
    { "$match": { 
        "idc": req.query.idc, "customer": req.query.customer}
    } ,
    { "$group": { 
        "_id": {
            "cluster": "$cluster",
            "idc":"$idc",
            "type": "$type"
        },
        "SumCores": { "$sum":"$cores" },
        "SumMemory": { "$sum":"$memory" }
    }},
    { "$group": {
        "_id": {
            "cluster": "$_id.cluster",
            "idc": "$_id.idc"
        },
        "data": {
            "$push": {
                "type": "$_id.type",
                "SumCores": "$SumCores",
                "SumMemory": "$SumMemory"
            }
        }
    }},
    { "$sort" : { "_id.idc": -1, "_id.cluster": 1 } }
]);

这会给你:

{
        "_id" : {
                "cluster" : 1,
                "idc" : "LH8"
        },
        "data" : [
                {
                        "type" : "Virtual",
                        "SumCores" : 232,
                        "SumMemory" : 469
                },
                {
                        "type" : "Physical",
                        "SumCores" : 256,
                        "SumMemory" : 1024
                }
        ]
}
{
        "_id" : {
                "cluster" : 1,
                "idc" : "LH5"
        },
        "data" : [
                {
                        "type" : "Virtual",
                        "SumCores" : 112,
                        "SumMemory" : 384
                },
                {
                        "type" : "Physical",
                        "SumCores" : 192,
                        "SumMemory" : 768
                }
        ]
}

但如果你真的必须,那么你可以从数组中过滤出匹配的元素并将它们放在它们自己的属性中:

Machine.aggregate([ 
    { "$match": { 
        "idc": req.query.idc, "customer": req.query.customer}
    } ,
    { "$group": { 
        "_id": {
            "cluster": "$cluster",
            "idc":"$idc",
            "type": "$type"
        },
        "SumCores": { "$sum":"$cores" },
        "SumMemory": { "$sum":"$memory" }
    }},
    { "$group": {
        "_id": {
            "cluster": "$_id.cluster",
            "idc": "$_id.idc"
        },
        "data": {
            "$push": {
                "type": "$_id.type",
                "SumCores": "$SumCores",
                "SumMemory": "$SumMemory"
            }
        }
    }},
    { "$project": {
        "Physical": {
            "$setDifference": [
                { "$map": {
                    "input": "$data",
                    "as": "el",
                    "in": {
                        "$cond": [
                            { "$eq": [ "$$el.type", "Physical" ] },
                            {
                                "SumCores": "$$el.SumCores",
                                "SumMemory": "$$el.SumMemory"
                            },
                            false
                        ]
                    }
                }},
                [false]
            ]
        },
        "Virtual": {
            "$setDifference": [
                { "$map": {
                    "input": "$data",
                    "as": "el",
                    "in": {
                        "$cond": [
                            { "$eq": [ "$$el.type", "Virtual" ] },
                            {
                                "SumCores": "$$el.SumCores",
                                "SumMemory": "$$el.SumMemory"
                            },
                            false
                        ]
                    }
                }},
                [false]
            ]
        }
    }},
    { "$unwind": "$Physical" },
    { "$unwind": "$Virtual"},
    { "$sort" : { "_id.idc": -1, "_id.cluster": 1 } }
]);

这给了你结果:

{
        "_id" : {
                "cluster" : 1,
                "idc" : "LH8"
        },
        "Physical" : {
                "SumCores" : 256,
                "SumMemory" : 1024
        },
        "Virtual" : {
                "SumCores" : 232,
                "SumMemory" : 469
        }
}
{
        "_id" : {
                "cluster" : 1,
                "idc" : "LH5"
        },
        "Physical" : {
                "SumCores" : 192,
                "SumMemory" : 768
        },
        "Virtual" : {
                "SumCores" : 112,
                "SumMemory" : 384
        }
}

但第一个只是为您提供相同的基本数据,而不需要额外传递结果。

无论如何,它实际上只是一个额外的$group 将它们组合在一起,然后是可选阶段(如果您真的必须拥有该数据格式)。但我会亲自处理代码中需要处理的任何对“对”的访问。

关于MongoDB - 聚合多行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32628218/

有关MongoDB - 聚合多行的更多相关文章

  1. ruby-on-rails - 如何在 ruby​​ 交互式 shell 中有多行? - 2

    这可能是个愚蠢的问题。但是,我是一个新手......你怎么能在交互式ruby​​shell中有多行代码?好像你只能有一条长线。按回车键运行代码。无论如何我可以在不运行代码的情况下跳到下一行吗?再次抱歉,如果这是一个愚蠢的问题。谢谢。 最佳答案 这是一个例子:2.1.2:053>a=1=>12.1.2:054>b=2=>22.1.2:055>a+b=>32.1.2:056>ifa>b#Thecode‘if..."startsthedefinitionoftheconditionalstatement.2.1.2:057?>puts"f

  2. ruby - Sublime Text 3 多行法折叠 - 2

    所以...SublimeText具有折叠方法的内置功能,但是一旦方法声明跨越多行,它就会失去这种能力。有谁知道插件或使它工作的方法吗?具体来说,我在使用ruby​​时遇到了这个问题(我的团队遵守关于行长度的严格风格指南),但语言应该无关紧要。 最佳答案 无需单击出现在函数定义第一行旁边的装订线中的向下箭头,您需要做的就是将光标放在函数的一个缩进行上(不是缩进的函数参数,而是在函数定义本身)并使用CtrlShift[键绑定(bind)(在OSX上使用⌘Alt[)折叠函数及其参数。使用CtrlShift](⌘Alt]在OSX上)展开,或

  3. ruby-on-rails - Dotenv 多行变量 - 2

    我正在使用dotenv.ARubygemtoloadenvironmentvariablesfrom.env.我的.env文件中是否可以包含多行变量?例如SOMETHING_CERTIFICATE="-----BEGINCERTIFICATE-----JSDFALDAFSSKLABVCXZLV2314IH4IHDFG9AYDF9DSSDF82QWEIWFHDSSD8SADF0=-----ENDCERTIFICATE-----"^上面的内容只会在中间那一行抛出一个错误,就好像它不是字符串的一部分,我正在尝试创建一个格式不正确的变量。 最佳答案

  4. ruby - Rails Elasticsearch 聚合 - 2

    不知何故,我似乎无法获得包含我的聚合的响应...使用curl它按预期工作:HBZUMB01$curl-XPOST"http://localhost:9200/contents/_search"-d'{"size":0,"aggs":{"sport_count":{"value_count":{"field":"dwid"}}}}'我收到回复:{"took":4,"timed_out":false,"_shards":{"total":5,"successful":5,"failed":0},"hits":{"total":90,"max_score":0.0,"hits":[]},"a

  5. c# - Ruby 等效于 C# Linq 聚合方法 - 2

    什么是Linq聚合方法的ruby​​等价物。它的工作原理是这样的varfactorial=new[]{1,2,3,4,5}.Aggregate((acc,i)=>acc*i);每次将数组序列中的值传递给lambda时,变量acc都会累积。 最佳答案 这在数学以及几乎所有编程语言中通常称为折叠。它是更普遍的变形概念的一个实例。Ruby从Smalltalk中继承了这个特性的名称,它被称为inject:into:(像aCollectioninject:aStartValueinto:aBlock一样使用。)所以,在Ruby中,它称为inj

  6. ruby - 如何在不使用 HERE-DOCUMENT 语法的情况下在 Ruby 中制作多行字符串文字? - 2

    问题总结我想尝试使用Ruby来完成我在Python中所做的事情。在Python中它有r"""syntaxtosupportrawstrings,这很好,因为它允许将原始字符串与代码内联,并以更自然的方式连接它们,而无需特殊缩进。在Ruby中,当使用原始字符串时,必须使用其次是EOT在单独的行中,这会破坏代码布局。你可能会问,为什么不使用Ruby的%q{}?嗯,因为%q{}与Python的r"""相比有局限性因为它不会转义多个\\\并且只处理单个\.我正在动态生成Latex代码并写入一个文件,该文件稍后用pdflatex编译。Latex代码包含类似\\\的内容在许多地方。如果我使用Rub

  7. ruby - 如何在 Cucumber 表(多行参数)中使用正则表达式来区分表? - 2

    我正在使用场景表(multilinesteparguments)使用内置的.diff来使用cucumber检查来自屏幕的一些数据!CucumberAST表上的方法。我想检查内容是否与正则表达式匹配。Scenario:OneThenthetableappearsas:|One|Two|Three||/\d+/|/\d+/|/\d+/|实际的表格看起来像|One|Two|Three||123|456|789|这个场景翻译成“只要有几个数字,我不在乎”失败的示例步骤实现:Then/^thetableappearsas:$/do|expected_table|actual_table=[['O

  8. ruby-on-rails - 编写多行 ActiveRelation 查询的惯用方法是什么? - 2

    我的应用程序中有许多多行ActiveRelation查询方法,我不确定编写这些方法的最惯用方式。看看这个例子:defpostal_code_ids_within(miles)nearby_postal_codes=PostalCode.where("latitude>:min_latandlatitude:min_lonandlongitude我觉得有点不对劲。从中返回ActiveRelation对象的block似乎是惯用的,但我还没有看到这种方法。什么是标准? 最佳答案 根据Brian的建议,这更易读并且效果很好。scope:ne

  9. ruby - ruby 中带有多行字符串的空格 - 2

    我有一个多行字符串的空白问题。我在生成一些SQL的代码中有类似的内容。defgenerate_sql但是我的SQL缩进全乱了,这是我不想要的。"UPDATEpage\nSETview_count=10;\n"我能做到defgenerate_sql输出的正是我想要的"UPDATEpage\nSETview_count=10;\n"但是我的代码缩进全乱了,我真的不想要这样。关于如何最好地实现我所追求的目标有什么建议吗? 最佳答案 Ruby2.3.0使用squigglyheredoc很好地解决了这个问题.请注意示例之间波浪号/连字符的区别

  10. ruby-on-rails - 如何格式化多行 RSpec expect {}.to change - 2

    是否有更好的方法来格式化此测试以使其更具可读性?expect{within'.foo'doclick_link'Delete'end}.tochange{Foo.count}.by1期望do...end有效,但更丑陋... 最佳答案 也许是这样的?expected=expectdowithin'.foo'doclick_link'Delete'endendexpected.tochange{Foo.count}.by1不是很漂亮,但减少了一些线路噪音。 关于ruby-on-rails-如

随机推荐