有没有办法在 MongoDB 中获取具有 WHERE (SQL) 等条件的字段总和

Posted

技术标签:

【中文标题】有没有办法在 MongoDB 中获取具有 WHERE (SQL) 等条件的字段总和【英文标题】:Is there a way to get sum of field with a condition like WHERE (SQL) in MongoDB 【发布时间】:2015-04-28 08:29:14 【问题描述】:

我正在寻找一种在我的 mongodb 中获取字段总和的方法。我的数据库如下所示:


    "_id" : ObjectId("553f35b8bfabe235158b4f4b"),
    "event_id" : NumberLong(342),
    "ticket_id" : NumberLong(85326),
    "ticket_code" : NumberLong(3445345345343),
    "ticket_type_id" : NumberLong(42),
    "ticket_created" : NumberLong(1429866042),
    "ticket_deleted" : NumberLong(0),
    "ticket_user_id" : NumberLong(3207),
    "ticket_used" : NumberLong(0),
    "order_id" : NumberLong(6988),
    "order_code" : NumberLong(444234),
    "order_created" : NumberLong(1429866042),
    "order_deleted" : NumberLong(0),
    "order_sales_pipeline" : NumberLong(1),
    "order_invoice_id" : NumberLong(4194),
    "order_invoice_amount" : 25000.0000000000000000,
    "order_invoice_created" : NumberLong(1429866053),
    "order_invoice_deleted" : NumberLong(0),
    "order_invoice_code" : NumberLong(419338),
    "payment_id" : NumberLong(4355),
    "payment_amount" : 25000.0000000000000000,
    "payment_currency" : NumberLong(2),
    "payment_author_id" : NumberLong(159),
    "payment_type_id" : NumberLong(2),
    "payment_created" : NumberLong(1429866053),
    "payment_deleted" : NumberLong(0),
    "create_time" : ISODate("2015-04-28T07:24:40.289Z")

我需要得到带有条件的 payment_amount 字段的总和,我在 SQL 中是这样的:

SELECT SUM(payment_amount) as total FROM ticket_cache WHERE event_id = 342 AND ticket_type IN(84, 45, 365)

在 mongodb 中是否有相同的方法?

【问题讨论】:

更多信息请喜欢你的数据库结构和你想要什么结果? 当然,它是一个聚合函数。看这里:docs.mongodb.org/manual/reference/operator/aggregation/sum 【参考方案1】:

是的,通过 mongodb 的 aggregation framework。例如,以下将订单集合中的价格字段求和,其中文档字段符合特定条件:

db.orders.aggregate([
    
        "$match": 
            "field1": "a",
            "field2": "b"
        
    ,
    
        "$group": 
           "_id": null,
           "total":  "$sum": "$price" 
        
   
]);

等效 SQL

SELECT SUM(price) AS total
FROM orders
WHERE field1 = 'a' AND field2 = 'b'

更多示例,您可以参考文档SQL to Aggregation Mapping Chart

-- 更新--

使用您的文档架构,要获得条件 event_id 为 342 AND ticket_type IN (84, 45, 365) 的 payment_amount 字段的总和,请使用以下以 $match 开头的聚合管道管道阶段,使用给定条件过滤文档,然后使用 $group 运算符对过滤后的文档进行分组,以计算字段 payment_amount 的总和:

var pipeline = [
    
        "$match": 
            "event_id": 342,
            "ticket_type":  "$in": [84, 45, 365] 
        
    ,
    
         "$group": 
             "_id": null,
             "total":  "$sum": "$payment_amount" 
         
    
];
db.collection.aggregate(pipeline);

【讨论】:

@Kossgreim 不用担心 :-)【参考方案2】:

你可以使用 Mongo 的map-reduce,

比如这个sql查询:

SELECT SUM(payment_amount) as total FROM ticket_cache WHERE event_id = 342 AND ticket_type IN(84, 45, 365)

相当于这个map-reduce:

db.ticket_cache.mapReduce(
                     function () 
                       emit(this._id,
                         (([84, 45, 365].indexOf(this.ticket_type)>-1)&&(this.event_id==342) ?
                         this.payment_amount : 0) );
                     ,//mapper
                     function(id, payment_amount) 
                        return Array.sum(payment_amount);
                     ,//reducer
                      out: "conditional_sum_example" 
                   )

【讨论】:

可以使用 map-reduce,但不是最简单的方法。我认为聚合管道是一种更好的求和方式 以什么方式更好?在 mongo 以及其他 nosql dbs 中,事情作为 map-reduce 运行。 是的,这是真的,但更难将 map reduce 理解为简单的聚合查询,并且查询应该比 map-reduce 更快【参考方案3】:
Try:
db.ticket_cache.aggregate(
   [
      $match :  event_id : 342, ticket_type :  $in: [84, 45, 365] ,
     
       $group:
         
           _id:  event_id: "$event_id" ,
           totalAmount:  $sum: $payment_amount ,
           count:  $sum: 1 
         
     
   ]
)

【讨论】:

以上是关于有没有办法在 MongoDB 中获取具有 WHERE (SQL) 等条件的字段总和的主要内容,如果未能解决你的问题,请参考以下文章

NextJS getServerSideProps() 具有多个获取请求

Mongodb Document : 有没有办法计算有条件的子文档?

mongoDB有没有办法在特定时间后自己创建一个文档,比如一天?

如何获取 mongodb 模式转储

MongoDB - 获取具有不同的数组

MongoDB:从数组的开头删除一定数量的元素