【问题标题】:Is there a way to get sum of field with a condition like WHERE (SQL) in MongoDB有没有办法在 MongoDB 中获取具有 WHERE (SQL) 等条件的字段总和
【发布时间】:2023-03-23 21:57:01
【问题描述】:

我正在寻找一种在我的 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 中是否有相同的方法?

【问题讨论】:

标签: php sql mongodb


【解决方案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 }
         }
     }
   ]
)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-03
    • 2023-01-13
    • 1970-01-01
    • 2018-03-02
    • 2015-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多