【问题标题】:Error from mongo aggregate pipeline with $merge来自带有 $merge 的 mongo 聚合管道的错误
【发布时间】:2021-09-08 03:04:38
【问题描述】:

我有一个简单的集合 alert 带有 _id 和 observables 数组

例如

{
  _id: '60d496b2d08d5f0630dea368',
  observables: ['10d496b2d08d5f0630dea368', '20d496b2d08d5f0630dea368'],
}

我创建了查询来创建没有数组的新集合,格式如下:

{
  _id: <default id>,
  alertId: '60d496b2d08d5f0630dea368',
  observableId: '10d496b2d08d5f0630dea368',
{
  _id: <default id>,
  alertId: '60d496b2d08d5f0630dea368',
  observableId: '20d496b2d08d5f0630dea368',
}

另外,为了防止重复,创建了唯一索引

collection.createIndex({ observableId: 1, alertId: 1 }, { unique: true });

这是我的查询:

db.collection.aggregate([
  {
    "$unwind": "$observables"
  },
  {
    "$project": {
      _id: 0,
      observableId: "$observables",
      alertId: "$_id"
    }
  },
  {
    "$merge": {
      into: {
        db: "some-db",
        coll: "some-coll"
      },
      on: [
        "observableId",
        "alertId"
      ]
    }
  }
])

结果出现错误 *MongoError: Cannot find index to verify that join fields will be unique

但是索引已经创建,所以知道如何解决这个错误吗?

链接到mongoplayground

【问题讨论】:

  • 删除 $merge 的 on 部分。
  • 您确定唯一索引在正确的数据库和集合上吗?

标签: mongodb indexing aggregation-framework


【解决方案1】:

您可以但不需要创建该索引,您需要的是生成一个唯一的_id 值。

由于您要合并到现有集合中而不是输出到新集合中,我建议您创建一个 _id 字段,该字段由 _id 和 observables 字段的串联构建

例如使用$toString 和$concat:

"_id": {$concat: [{$toString: "$_id"}, "-", {$toString: "$observables"}]}

这样您就有了一个可重复的过程,其中运行两次将产生相同的_id 值。

您可以使用以下方法合并到现有集合中:

{ $merge: { into: ..., on: "_id", whenMatched: "keepExisting", whenNotMatched: "insert" } }

完整示例:

db.collection.aggregate([
  {
    "$unwind": "$observables"
  },
  {
    "$project": {
      _id: {$concat: [
        {$toString: "$_id"},
        "-",
        {$toString: "$observables"}
      ]},
      observableId: "$observables",
      alertId: "$_id"
    }
  },
  {
    "$merge": {
      into: {db: "some-db", coll: "some-coll"},
      on: "_id"
    }
  }
])

关于你实现它的方式,我的猜测是索引在错误的数据库或集合上,即不在输出集合上。

【讨论】:

  • 我从docs.mongodb.com/manual/reference/operator/aggregation/merge/… 读到“如果结果文档中缺少_id 字段,MongoDB 会自动添加它”,因为您不需要生成_id。删除它应该足以让 mongo 生成新的 ObjectId。我错了吗?
  • 它会自动添加它,但是,额外的唯一索引会减慢速度,您可以使用 _id 代替。
  • 啊,我明白你的意思了。有道理。
【解决方案2】:

问题出在排序规则中。

索引排序规则和查询(在我的例子中为db.collection.aggregate)应该具有相同的排序规则

【讨论】:

    猜你喜欢
    • 2020-10-16
    • 2021-07-10
    • 2021-07-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-26
    • 1970-01-01
    • 2022-01-27
    相关资源
    最近更新 更多