我遇到了聚合问题,因为我需要更新对象数组中的分析值.

我有一个聚合,它生成如下对象:

{
  "key": "product1",
  "analytics": [
    {
      "type": "CLICK",
      "value": 2
    },
    {
      "type": "SELL",
      "value": 19.99
    }

  ]
}

管道末端:

{
$merge: {
      into: 'analytics',
      on: ['key'],
      whenMatched: [ // <- MIGHT BE HERE SOME PREP CODE USING $$new
        {
          $replaceWith: {
            key: '$key',
            analytics: {} // <- OR HERE?
          }
        }
      ],
      whenNotMatched: 'insert'
    }
}

因此,问题是这条管道每小时运行一次,收集所有新数据用于分析.按whenNotMatched条件添加新记录时运行正常.但我需要更新每个"类型"的"值"(用新值汇总旧值),如果它们不在analytics数组中,则添加新的"类型".

例如:

我们有了这个物体:

{
  "key": "product1",
  "analytics": [
    {
      "type": "CLICK",
      "value": 2
    },
    {
      "type": "SELL",
      "value": 19.99
    }

  ]
}

在另一条管道运行后,我们有了:

{
  "key": "product1",
  "analytics": [
    {
      "type": "CLICK",
      "value": 5
    },
    {
      "type": "SELL",
      "value": 29.99
    },
    {
      "type": "ABANDON",
      "value": 1
    }
  ]
}

合并后,我们应该有:

{
  "key": "product1",
  "analytics": [
    {
      "type": "CLICK",
      "value": 7
    },
    {
      "type": "SELL",
      "value": 49.98
    },
    {
      "type": "ABANDON",
      "value": 1
    }
  ]
}

推荐答案

一个复杂的查询.

  1. $map -迭代$$new.analytics数组中的每个元素.

1.1 $cond-判断迭代元素的type是否存在于现有的analytics数组中.如果是,则转到第1.1.1节.否则,返回newItem对象.

1.1.1.$first-从结果1.1.1.1返回第一个文档.

1.1.1.1.$map-迭代现有analytics数组的匹配元素,返回该元素,并通过添加新的value来覆盖现有的value.

  {
    $merge: {
      into: "analytics",
      on: [
        "key"
      ],
      whenMatched: [
        {
          $replaceWith: {
            key: "$key",
            analytics: {
              $map: {
                input: "$$new.analytics",
                as: "newItem",
                in: {
                  $cond: [
                    {
                      $in: [
                        "$$newItem.type",
                        "$analytics.type"
                      ]
                    },
                    {
                      $first: {
                        $map: {
                          input: {
                            $filter: {
                              input: "$analytics",
                              cond: {
                                $eq: [
                                  "$$this.type",
                                  "$$newItem.type"
                                ]
                              }
                            }
                          },
                          as: "oldItem",
                          in: {
                            $mergeObjects: [
                              "$$newItem",
                              {
                                value: {
                                  $sum: [
                                    "$$oldItem.value",
                                    "$$newItem.value"
                                  ]
                                }
                              }
                            ]
                          }
                        }
                      }
                    },
                    "$$newItem"
                  ]
                }
              }
            }
          }
        }
      ],
      whenNotMatched: "insert"
    }
  }

此外,这是支持$let运算符的另一个版本:

{
    $merge: {
      into: "analytics",
      on: ["key"],
      whenMatched: [
        {
          $replaceWith: {
            key: "$key",
            analytics: {
              $map: {
                input: "$$new.analytics",
                as: "newItem",
                in: {
                  $cond: [
                    {
                      $in: [
                        "$$newItem.type",
                        "$analytics.type"
                      ],
                    },
                    {
                      $let: {
                        vars: {
                          oldItem: {
                            $first: {
                              $filter: {
                                input:
                                  "$analytics"
                                cond: {
                                  $eq: [
                                    "$$this.type",
                                    "$$newItem.type"
                                  ]
                                }
                              }
                            }
                          }
                        },
                        in: {
                          $mergeObjects: [
                            "$$newItem",
                            {
                              value: {
                                $sum: [
                                  "$$oldItem.value",
                                  "$$newItem.value"
                                ]
                              }
                            }
                          ]
                        }
                      }
                    },
                    "$$newItem"
                  ]
                }
              }
            }
          }
        }
      ],
      whenNotMatched: "insert"
    }
  }

Mongodb相关问答推荐

从两个相连的文件中获取电话和邮箱的渠道是什么?

字段$set聚合导致错误美元($)前缀字段$concatArrays对于存储无效"

MongoDB-如何过滤和获取数组字段中的最新数据

Mongo Aggregate管道-另一个集合中的多个查找

MongoDB - 将属性添加到数组中的对象(如果不存在)

对 MongoDB 集合中的对象数组进行排序

Mongodb聚合中基于其他字段值的多个条件的动态新字段值

MongoDB 查询以包含多个字段的最常见值的计数

MongoDB C# 驱动程序 2.0 InsertManyAsync 与 BulkWriteAsync

使用 Node.js 通过 SSL 连接到 MongoDB

MongoDB C# 驱动程序 - 如何将 _id 存储为 ObjectId 但映射到字符串 Id 属性?

子文档上的mongoose唯一索引

获取收集字节使用情况统计信息的pymongo方法?

如何使用sailsjs v0.10连接mongodb?

python mongodb正则表达式:忽略大小写

在 GridFS、express、mongoDB、node.js 中存储来自 POST 请求的数据流

具有 AWS 云形成和自动zoom 的 Mongodb 集群

如何仅通过一次调用将一组对象保存到mongoose数据库?

MongoDB 和 Robomongo: Can't connect (authentication)

Mongoose 为所有嵌套对象添加 _id