首页 > 解决方案 > Python 中的复杂 Mongo 查询

问题描述

我有一个名为measurements. 在这个集合中,只有三个字段:id(univoque)、tmstamp(univoque) 和value. 包含大于 0 的值的每一行都被视为警报。从零状态到下一个零状态发生的所有警报都被视为一个情节。我想以剧集格式返回数据的方式查询数据。也就是说,每一行都是一个插曲。

为了更容易理解,我举个例子:

{"id":1, tmstamp:1577644027, value:0}
{"id":2, tmstamp:1577644028, value:0}
{"id":3, tmstamp:1577644029, value:1}
{"id":4, tmstamp:1577644030, value:1}
{"id":5, tmstamp:1577644031, value:2}
{"id":6, tmstamp:1577644032, value:2}
{"id":7, tmstamp:1577644033, value:3}
{"id":8, tmstamp:1577644034, value:2}
{"id":9, tmstamp:1577644035, value:1}
{"id":10, tmstamp:1577644036, value:0}
{"id":11, tmstamp:1577644037, value:1}
{"id":12, tmstamp:1577644038, value:1}
{"id":13, tmstamp:1577644039, value:1}
{"id":14, tmstamp:1577644040, value:0}

鉴于这些数据,剧集将是:

episode1

{"id":3, tmstamp:1577644029, value:1}
{"id":4, tmstamp:1577644030, value:1}
{"id":5, tmstamp:1577644031, value:2}
{"id":6, tmstamp:1577644032, value:2}
{"id":7, tmstamp:1577644033, value:3}
{"id":8, tmstamp:1577644034, value:2}
{"id":9, tmstamp:1577644035, value:1}

episode2

{"id":11, tmstamp:1577644037, value:1}
{"id":12, tmstamp:1577644038, value:1}
{"id":13, tmstamp:1577644039, value:1}

我的问题是:有没有什么方法可以在 Mongo 中查询数据以获得这种格式的结果,而无需在查询本身之后执行这些操作?

标签: pythonmongodbpymongo

解决方案


您需要结合$facetArray expression operators
正如@aws_apprentice 所提到的,$bucket如果您知道以前的零状态度量 id's会为您做这件事,因为边界不接受表达式

所以,我们需要区分零状态和非零状态数据。我们称它们为:警报(值 = 0)和情节(值 > 1)。
对于alerts,我们将_id带有警报的每个测量值存储到数组中(我们需要它来过滤情节)。使用$indexOfArrayand$arrayElemAt我们可以获取下一个 _id i+1(过滤ii+1ids 之间的情节)。

假设

我已经替换id_id执行聚合
您知道如何在Python语法中翻译 MongoDB 聚合命令

db.measurements.aggregate([
  {
    $facet: {
      alerts: [
        {
          $match: {
            value: 0
          }
        },
        {
          $group: {
            _id: "",
            ids: {
              $push: "$_id"
            }
          }
        }
      ],
      episodes: [
        {
          $match: {
            value: {
              $gt: 0
            }
          }
        }
      ]
    }
  },
  {
    $unwind: "$alerts"
  },
  {
    $addFields: {
      alert_idx: "$alerts.ids"
    }
  },
  {
    $unwind: "$alerts.ids"
  },
  {
    $project: {
      "k": {
        $concat: [
          "Episode",
          {
            $toString: {
              $indexOfArray: [
                "$alert_idx",
                "$alerts.ids"
              ]
            }
          }
        ]
      },
      "v": {
        $filter: {
          input: "$episodes",
          cond: {
            $and: [
              {
                $gt: [
                  "$$this._id",
                  "$alerts.ids"
                ]
              },
              {
                $lt: [
                  "$$this._id",
                  {
                    $arrayElemAt: [
                      "$alert_idx",
                      {
                        $sum: [
                          {
                            $indexOfArray: [
                              "$alert_idx",
                              "$alerts.ids"
                            ]
                          },
                          1
                        ]
                      }
                    ]
                  }
                ]
              }
            ]
          }
        }
      }
    }
  },
  {
    $match: {
      "v": {
        $ne: []
      }
    }
  }
])

Mongo游乐场


推荐阅读