Mongodb Mongo基于字段删除对象数组中的重复项

Mongodb Mongo基于字段删除对象数组中的重复项,mongodb,aggregation-framework,Mongodb,Aggregation Framework,Mongo新手,已经发现了许多使用聚合框架从字符串数组中删除重复的示例,但是我想知道是否可以基于对象中的字段从对象数组中删除重复。乙二醇 { "_id" : ObjectId("5e82661d164941779c2380ca"), "name" : "something", "values" : [ { "id" : 1, "val" : "x" }, { "id" : 1, "val" : "x"

Mongo新手,已经发现了许多使用聚合框架从字符串数组中删除重复的示例,但是我想知道是否可以基于对象中的字段从对象数组中删除重复。乙二醇

{
"_id" : ObjectId("5e82661d164941779c2380ca"),
"name" : "something",
"values" : [
    {
        "id" : 1,
        "val" : "x"
    },
    {
        "id" : 1,
        "val" : "x"
    },
    {
        "id" : 2,
        "val" : "y"
    },
    {
        "id" : 1,
        "val" : "xxxxxx"
    }
]
}
在这里,我想根据
id
字段删除重复。因此,我们将以

{
"_id" : ObjectId("5e82661d164941779c2380ca"),
"name" : "something",
"values" : [
    {
        "id" : 1,
        "val" : "x"
    },
    {
        "id" : 2,
        "val" : "y"
    }
]
}
拾取具有给定id的第一个/任何对象都有效。只希望每个id有一个。这在聚合框架中可行吗?或者甚至在聚合框架之外,只是寻找一种干净的方法来实现这一点。需要跨集合中的许多文档执行此类操作,这似乎是聚合框架的一个很好的用例,但正如我所提到的,这里的新手…谢谢。

您可以使用,请尝试以下查询:

db.collection.aggregate([
  {
    $addFields: {
      values: {
        $reduce: {
          input: "$values",
          initialValue: [],
          in: {
            $cond: [
              { $in: ["$$this.id", "$$value.id"] }, /** Check if 'id' exists in holding array if yes push same array or concat holding array with & array of new object */
              "$$value",
              { $concatArrays: ["$$value", ["$$this"]] }
            ]
          }
        }
      }
    }
  }
]);

测试:

好吧,你可以通过两种方式得到想要的结果

经典 展平-删除重复项(拾取第一个引用)-分组方式

db.collection.aggregate([
  {
    $unwind: "$values"
  },
  {
    $group: {
      _id: "$values.id",
      values: {
        $first: "$values"
      },
      id: {
        $first: "$_id"
      },
      name: {
        $first: "$name"
      }
    }
  },
  {
    $group: {
      _id: "$id",
      name: {
        $first: "$name"
      },
      values: {
        $push: "$values"
      }
    }
  }
])

现代的 我们需要使用运算符

伪代码:

values : {
  var tmp = [];
  for (var value in values) {
      if !(value.id in tmp)
        tmp.push(value);
  }
  return tmp;
}


正在键入解释:D@Valijon:不明白你在说什么?我发布了相同的解决方案,并在写解释。但是你已经发布了first@Valijon:-):-)谢谢!“经典”和“现代”在性能或处理大型收藏方面有什么不同/偏好吗?@chacmool需要尝试一下。如果你想看到一个基准,让我知道。爱只会反应
db.collection.aggregate([
  {
    $addFields: {
      values: {
        $reduce: {
          input: "$values",
          initialValue: [],
          in: {
            $concatArrays: [
              "$$value",
              {
                $cond: [
                  {
                    $in: [
                      "$$this.id",
                      "$$value.id"
                    ]
                  },
                  [],
                  [
                    "$$this"
                  ]
                ]
              }
            ]
          }
        }
      }
    }
  }
])