草庐IT

MongoDB 聚合 $group 和 $match 组结果

coder 2023-11-01 原文

我有一个集合如下

{

    "_id" : ObjectId("553b2c740f12bb30f85bd41c"),
    "symbol" : "EUR/GBP",
    "order_id" : "PW_BarclaysTrades60530",
    "ticket_id" : "PW_BarclaysTrades.60530",
    "basketid" : "TESTBASKET-1428483828043",
    "date_sent" : ISODate("2015-04-07T18:30:00.000Z"),
    "destination" : "BarclaysTrades",
    "order_price" : 0.0000000000000000,
    "order_quantity" : 4000000.0000000000000000,
    "order_type" : 1.0000000000000000,
    "parent_quantity" : 250000000.0000000000000000,
    "time_sent" : "09:03:48",
    "side" : 1,
    "tif" : "0",
    "execution_id" : 88939,
    "date_recvd" : ISODate("2015-04-07T18:30:00.000Z"),
    "exe_quantity" : 50000.0000000000000000,
    "time_recvd" : "09:03:48",
    "execution_price" : 2.5000000000000000,
    "execution_type" : 1
}

我想获取集合中每个目的地的 execution_price 大于 average(execution_price) 的文档

尝试按如下方式聚合:

db.orders_by_symbol.aggregate( [
{ $limit:300000 },
{ $match:{ destination: "PAPER" } },
{ $group:{_id:{Destination:"$destination"},avg_exec_price:  
              {$avg:"$execution_price"} ,"data":{"$push": "$$ROOT"}}},
{$unwind:"$data"},
{$match:{execution_price:{$ne: "$avg_exec_price"}}},
{$project:{_id:0,symbol:"$data.symbol",destination:"$data.destination",
          execution_id:"$data.execution_id",
          exec_price:"$data.execution_price",
         avg_ex_price:"$avg_exec_price"}}], 
{allowDiskUse:true})

得到如下结果

{

    "result" : [ 
        {
            "symbol" : "EUR/GBP",

            "destination" : "PAPER",
            "execution_id" : 89109,
            "exec_price" : 6.5000000000000000,
            "avg_ex_price" : 95.0747920857049140
        }, 
        {
            "symbol" : "EUR/GBP",
            "destination" : "PAPER",
            "execution_id" : 89110,
            "exec_price" : 6.0000000000000000,
            "avg_ex_price" : 95.0747920857049140
        }, 
        {
            "symbol" : "EUR/GBP",
            "destination" : "PAPER",
            "execution_id" : 89111,
            "exec_price" : 6.5000000000000000,
            "avg_ex_price" : 95.0747920857049140
        }

但是,当我将“$ne”运算符更改为“$gt”时,不会产生任何结果。 exec_price 和 avg_ex_price 都是双数据类型。不确定为什么它没有按预期工作。

最佳答案

使用 MongoDB Server 3.6 及更新版本:

var pipeline = [
    { "$match": { "destination": "PAPER" } },
    { "$facet": {
        "average": [
            { "$group": {
                "_id": null,
                "avg_exec_price": { "$avg": "$execution_price" }
            } }
        ],
        "data": [
            { "$project": { 
                "_id": 0,
                "symbol": 1,
                "destination": 1,
                "execution_id": 1,
                "execution_price": 1
            } }                   
        ]
    } },
    { "$addFields": {
        "average": { "$arrayElemAt": ["$average", 0] }
    } },
    { "$addFields": {
        "data": { 
            "$filter" : {
                "input": {
                    "$map": {
                        "input": "$data",
                        "as": "el",
                        "in": {
                            "symbol": "$$el.symbol",
                            "destination": "$$el.symbol",
                            "execution_id": "$$el.symbol",
                            "exec_price": "$$el.execution_price",
                            "avg_exec_price": "$average.avg_exec_price"
                        }
                    }
                },
                "as": "doc",
                "cond": {
                    "$gt" : [ 
                        "$$doc.exec_price", 
                        "$$doc.avg_exec_price"
                    ]
                }
            }
        }
    } },  
    { "$unwind": "$data" },  
    { "$replaceRoot": {  "newRoot": "$data" } }
];

对于不支持上述运算符和管道的 MongoDB 版本,请使用 $project运算符创建一个附加字段,通过 $gt 存储两个字段的比较聚合运算符:

var pipeline = [
    { "$match": {
        "destination": "PAPER"
    } },
    { "$group": {
        "_id": null,
        "avg_exec_price": { "$avg": "$execution_price" },
        "data": { "$addToSet": "$$ROOT" }
    } },
    { "$unwind": "$data" },
    { "$project": { 
        "_id": 0,
        "data": 1,
        "avg_exec_price": 1,            
        "isGreaterThanAverage": { 
            "$gt" : [ "$data.execution_price", "$avg_exec_price" ] 
        }
    } },    
    { "$match": {            
        "isGreaterThanAverage": true
    } },
    { "$project": { 
        "_id": 0,
        "symbol": "$data.symbol",
        "destination": "$data.destination",
        "execution_id": "$data.execution_id",
        "exec_price": "$data.execution_price",
        "avg_ex_price": "$avg_exec_price"
    } }
];

现在要测试上述聚合,假设您有以下最小测试用例集合:

db.test.insert([{
    "symbol" : "EUR/GBP",    
    "destination" : "PAPER",    
    "execution_id" : 88939,    
    "execution_price" : 1.8
},
{
    "symbol" : "EUR/GBP",    
    "destination" : "PAPER",    
    "execution_id" : 88921,    
    "execution_price" : 6.8
},
{
    "symbol" : "USD/GBP",    
    "destination" : "foo",    
    "execution_id" : 88955,    
    "execution_price" : 3.1
},
{
    "symbol" : "AUD/GBP",    
    "destination" : "PAPER",    
    "execution_id" : 88941,    
    "execution_price" : 1.1
},
{
    "symbol" : "EUR/GBP",    
    "destination" : "PAPER",    
    "execution_id" : 88907,    
    "execution_price" : 9.4
}]);

运行上面的聚合

db.test.aggregate(pipeline);

将产生结果:

/* 0 */
{
    "result" : [ 
        {
            "symbol" : "EUR/GBP",
            "destination" : "PAPER",
            "execution_id" : 88907,
            "exec_price" : 9.4,
            "avg_ex_price" : 4.775
        }, 
        {
            "symbol" : "EUR/GBP",
            "destination" : "PAPER",
            "execution_id" : 88921,
            "exec_price" : 6.8,
            "avg_ex_price" : 4.775
        }
    ],
    "ok" : 1
}

关于MongoDB 聚合 $group 和 $match 组结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29958579/

有关MongoDB 聚合 $group 和 $match 组结果的更多相关文章

  1. 报告回顾丨模型进化狂飙,DetectGPT能否识别最新模型生成结果? - 2

    导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri

  2. ruby-on-rails - rails group by 和 order by column - 2

    在我的Controller中,我得到了按类别分组的所有Extras:defindex@categories=Extra.all.group_by(&:category)end结果类似于哈希数组:{#=>[#,#=>[#,#]}我想按类别“排序”列而不是id排序,它应该如下所示:{#=>[#,#=>[#,#]}当我尝试时:defindex@categories=Extra.all.group_by(&:category).sort_by{|s|s[:sort]}end我得到“没有将符号隐式转换为整数”。那是因为我在“sort_by”中使用了一个符号吗? 最佳答

  3. 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

  4. 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

  5. ruby - gem 推送结果为 "package metadata is missing" - 2

    我正在尝试将我更新的gem推送到ruby​​gems.com并得到以下结果。~/dev/V2/V2GPTI(master)$gembuildv2gpti.gemspecSuccessfullybuiltRubyGemName:v2gptiVersion:0.2File:v2gpti-0.2-universal-darwin-13.gem~/dev/V2/V2GPTI(master)$gempushv2gpti.gemspecERROR:Whileexecutinggem...(Gem::Package::FormatError)packagemetadataismissinginv2g

  6. ruby - 为什么 `Symbol#match` 的行为与 `String#match` 和 `Regexp#match` 不同? - 2

    String#match和Regexp#match在匹配成功时返回一个MatchData:"".match(//)#=>#//.match("")#=>#//.match(:"")#=>#但是Symbol#match返回匹配位置(如String#=~)::"".match(//)#=>0为什么Symbol#match表现不同?有用例吗? 最佳答案 我将其报告为Ruby核心中的错误:https://bugs.ruby-lang.org/issues/11991.让我们看看他们会怎么说。更新被质疑的行为似乎是一个错误。似乎从Ruby2.

  7. ruby , `match' : invalid byte sequence in UTF-8 - 2

    我对UTF-8编码有一些问题。我在这里阅读了一些帖子,但它仍然无法正常工作。这是我的代码:#!/bin/envruby#encoding:utf-8defdeterminefile=File.open("/home/lala.txt")file.eachdo|line|puts(line)type=line.match(/DOG/)puts('aaaaa')iftype!=nilputs(type[0])breakendendend这是我文件的前3行:;?lalalalal60000065535-1362490443-0000006334-0000018467-0000000041en

  8. ruby - 猴子修补 float 中缀运算符产生意想不到的结果 - 2

    重新定义Float#/似乎没有效果:classFloatdef/(other)"magic!"endendputs10.0/2.0#=>5.0但是当另一个中缀运算符Float#*被重新定义时,Float#/突然采用了新的定义:classFloatdef/(other)"magic!"enddef*(other)"spooky"endendputs10.0/2.0#=>"magic!"我很想知道是否有人可以解释这种行为的来源,以及其他人是否得到相同的结果。ruby:ruby2.0.0p353(2013-11-22)[x64-mingw32]要快速确认错误,请运行thisscript.

  9. ruby-on-rails - 尝试编辑时,Rails form_for 结果为 POST 而不是 PUT - 2

    我正在使用Rails4并遇到以下错误。RoutingErrorNoroutematches[POST]"/logs/1/meals/13/edit我正在使用:meal传递模型对象的form_for,并且编辑页面正确呈现。但是,Rails似乎并没有检查膳食对象是否已经保存,因此它一直尝试将表单发送到#create操作并尝试发出POST请求,而不是将表单发送到更新操作并进行当我点击提交时一个PUT请求。我如何让form_for识别我正在尝试更新现有对象并且需要PUT而不是POST?其他一切正常,我已经运行了所有迁移。我是Rails的新手,几乎一整天都在尝试自己解决这个问题。请帮忙!请注意,

  10. ruby - 为什么会.is_a?和 .class 给出相互矛盾的结果? - 2

    我有三个属于同一个类的对象。一个是通过Item.new创建的,另外两个是从数据库(Mongoid)中提取的。我将这些对象中的一个/任何一个传递给另一个方法,并通过is_a?检查该方法中的类型:definitialize(item,attrs=nil,options=nil)super(attrs,options)raise'invaliditemobject'unlessitem.is_a?(Item)好吧,这次加薪被击中了。所以我在Rails控制台中检查类、is_a和instance_of。我得到相互矛盾的结果。为什么它们有相同的class但只有其中一个是那个class的instan

随机推荐