每天计算不同组的运行总数

发布于 2025-01-31 17:47:56 字数 2383 浏览 5 评论 0 原文

我试图每天将一系列交易集成到所有者的总数中。 最初的集合看起来像这样:

[
  { "to": "A", "from": "0", "ts": 1 },
  { "to": "A", "from": "0", "ts": 1 },
  { "to": "B", "from": "0", "ts": 1 },
  { "to": "B", "from": "0", "ts": 2 },
  { "to": "C", "from": "0", "ts": 3 },
  { "to": "A", "from": "B", "ts": 4 }
]

我想得到的是这样的:

[
  {
    "ts": 1,
    "holdings": [
      { "owner": "0", "holdings": -3 },
      { "owner": "A", "holdings": 2 },
      { "owner": "B", "holdings": 1 }
    ]
  },
  {
    "ts": 2,
    "holdings": [
      { "owner": "0", "holdings": -4 },
      { "owner": "A", "holdings": 2 },
      { "owner": "B", "holdings": 2 }
    ]
  },
  {
    "ts": 4,
    "holdings": [
      { "owner": "0", "holdings": -5 },
      { "owner": "A", "holdings": 3 },
      { "owner": "B", "holdings": 1 },
      { "owner": "C", "holdings": 1 }
    ]
  }
]

我已经了解如何为我设置的单个 ts 生成它,但是我不知道如何在所有 ts 上进行操作。

单个 ts 的聚合管道看起来像:

db.collection.aggregate([
  // start with: { "to": "A", "from": "0", "ts": 1 }
  {
    // create a doc with an array with subset of fields:
    // { "_id": ObjectId("5a934e000102030405000000"),
    //  "data": [ { "change": 1, "owner": "A", "ts": "1" },
    //            { "change": -1, "owner": "0", "ts": "1" } ] }
    $project: {
      data: [
        {
          owner: '$to',
          ts: '$ts',
          change: 1,
        },
        {
          owner: '$from',
          ts: '$ts',
          change: -1,
        },
      ],
    },
  },
  {
    // unwind the array into 2 docs:
    //   { "_id": ObjectId("5a934e000102030405000000"), "data": { "change": 1, "owner": "A", "ts": "1" } },
    //   { "_id": ObjectId("5a934e000102030405000000"), "data": { "change": -1, "owner": "0", "ts": "1" } },
    $unwind: '$data',
  },
  {
    // use data as root:
    // { "data": { "change": 1, "owner": "A", "ts": "1" } },
    // { "data": { "change": -1, "owner": "0", "ts": "1" } }
    $replaceRoot: {
      newRoot: '$data',
    },
  },
  {
    // select day to calc totals
    $match: {
      ts: {
        $lt: 6,
      },
    },
  },
  {
    // sum totals, grouped by owner
    $group: {
      _id: '$owner',
      //_id: null,
      holdings: {
        $sum: '$change',
      },
    },
  },
])

这给出了特定日期的正确结果(在 Match 阶段中选择)。我不明白我现在如何将其概括为全天。

I'm trying to aggreate a collection of transactions into a running total of owners by day.
The initial collection looks like this:

[
  { "to": "A", "from": "0", "ts": 1 },
  { "to": "A", "from": "0", "ts": 1 },
  { "to": "B", "from": "0", "ts": 1 },
  { "to": "B", "from": "0", "ts": 2 },
  { "to": "C", "from": "0", "ts": 3 },
  { "to": "A", "from": "B", "ts": 4 }
]

What I would like to get is something like this:

[
  {
    "ts": 1,
    "holdings": [
      { "owner": "0", "holdings": -3 },
      { "owner": "A", "holdings": 2 },
      { "owner": "B", "holdings": 1 }
    ]
  },
  {
    "ts": 2,
    "holdings": [
      { "owner": "0", "holdings": -4 },
      { "owner": "A", "holdings": 2 },
      { "owner": "B", "holdings": 2 }
    ]
  },
  {
    "ts": 4,
    "holdings": [
      { "owner": "0", "holdings": -5 },
      { "owner": "A", "holdings": 3 },
      { "owner": "B", "holdings": 1 },
      { "owner": "C", "holdings": 1 }
    ]
  }
]

I've already understood how to generate this for a single ts that I'm setting, but I don't know how to do it across all ts.

The aggregation pipeline for a single ts looks like this:

db.collection.aggregate([
  // start with: { "to": "A", "from": "0", "ts": 1 }
  {
    // create a doc with an array with subset of fields:
    // { "_id": ObjectId("5a934e000102030405000000"),
    //  "data": [ { "change": 1, "owner": "A", "ts": "1" },
    //            { "change": -1, "owner": "0", "ts": "1" } ] }
    $project: {
      data: [
        {
          owner: '$to',
          ts: '$ts',
          change: 1,
        },
        {
          owner: '$from',
          ts: '$ts',
          change: -1,
        },
      ],
    },
  },
  {
    // unwind the array into 2 docs:
    //   { "_id": ObjectId("5a934e000102030405000000"), "data": { "change": 1, "owner": "A", "ts": "1" } },
    //   { "_id": ObjectId("5a934e000102030405000000"), "data": { "change": -1, "owner": "0", "ts": "1" } },
    $unwind: '$data',
  },
  {
    // use data as root:
    // { "data": { "change": 1, "owner": "A", "ts": "1" } },
    // { "data": { "change": -1, "owner": "0", "ts": "1" } }
    $replaceRoot: {
      newRoot: '$data',
    },
  },
  {
    // select day to calc totals
    $match: {
      ts: {
        $lt: 6,
      },
    },
  },
  {
    // sum totals, grouped by owner
    $group: {
      _id: '$owner',
      //_id: null,
      holdings: {
        $sum: '$change',
      },
    },
  },
])

This gives the correct result for a particular day (selected in the match stage). I don't understand how I can now generalize that to all days.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

二智少女猫性小仙女 2025-02-07 17:47:56

一种方法是使用 $ setWindowFields ,它具有内置的累积:

db.collection.aggregate([
  {
    $project: {
      ts: "$ts",
      data: [{owner: "$to", change: 1}, {owner: "$from", change: -1}]
    }
  },
  {$unwind: "$data"},
  {
    $group: {
      _id: {ts: "$ts",  owner: "$data.owner"},
      holdings: {$sum: "$data.change"}
    }
  },
  {
    $setWindowFields: {
      partitionBy: "$_id.owner",
      sortBy: {"_id.ts": 1},
      output: {
        cumulativeHoldings: {
          $sum: "$holdings",
          window: {documents: ["unbounded", "current"]}
        }
      }
    }
  },
  {
    $group: {
      _id: "$_id.ts",
      holdings: {$push: {owner: "$_id.owner", holdings: "$cumulativeHoldings"}}
    }
  }
])

One way to do it is using $setWindowFields, which has a built-in accumulation:

db.collection.aggregate([
  {
    $project: {
      ts: "$ts",
      data: [{owner: "$to", change: 1}, {owner: "$from", change: -1}]
    }
  },
  {$unwind: "$data"},
  {
    $group: {
      _id: {ts: "$ts",  owner: "$data.owner"},
      holdings: {$sum: "$data.change"}
    }
  },
  {
    $setWindowFields: {
      partitionBy: "$_id.owner",
      sortBy: {"_id.ts": 1},
      output: {
        cumulativeHoldings: {
          $sum: "$holdings",
          window: {documents: ["unbounded", "current"]}
        }
      }
    }
  },
  {
    $group: {
      _id: "$_id.ts",
      holdings: {$push: {owner: "$_id.owner", holdings: "$cumulativeHoldings"}}
    }
  }
])

Playground

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文