Mongo 根据字段删除对象数组中的重复项

cha*_*ool 2 mongodb aggregation-framework

Mongo 的新手,发现了很多使用聚合框架从字符串数组中删除重复项的示例,但我想知道是否可以根据对象中的字段从对象数组中删除重复项。例如

{
"_id" : ObjectId("5e82661d164941779c2380ca"),
"name" : "something",
"values" : [
    {
        "id" : 1,
        "val" : "x"
    },
    {
        "id" : 1,
        "val" : "x"
    },
    {
        "id" : 2,
        "val" : "y"
    },
    {
        "id" : 1,
        "val" : "xxxxxx"
    }
]
}
Run Code Online (Sandbox Code Playgroud)

在这里,我想根据该id领域删除欺骗。所以最终会

{
"_id" : ObjectId("5e82661d164941779c2380ca"),
"name" : "something",
"values" : [
    {
        "id" : 1,
        "val" : "x"
    },
    {
        "id" : 2,
        "val" : "y"
    }
]
}
Run Code Online (Sandbox Code Playgroud)

选择具有给定 id 的第一个/任何对象。只想最终每个 id 一个。这在聚合框架中可行吗?甚至在聚合框架之外,只是寻找一种干净的方法来做到这一点。需要在集合中的许多文档中执行此类操作,这似乎是聚合框架的一个很好的用例,但正如我所提到的,这里是新手...谢谢。

Val*_*jon 5

好吧,您可能会以两种方式获得所需的结果。

经典的

展平 - 删除重复项(选择第一个出现) - 分组依据

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"
      }
    }
  }
])
Run Code Online (Sandbox Code Playgroud)

蒙戈游乐场

现代的

我们需要使用$reduce运算符。

伪代码:

values : {
  var tmp = [];
  for (var value in values) {
      if !(value.id in tmp)
        tmp.push(value);
  }
  return tmp;
}
Run Code Online (Sandbox Code Playgroud)
db.collection.aggregate([
  {
    $addFields: {
      values: {
        $reduce: {
          input: "$values",
          initialValue: [],
          in: {
            $concatArrays: [
              "$$value",
              {
                $cond: [
                  {
                    $in: [
                      "$$this.id",
                      "$$value.id"
                    ]
                  },
                  [],
                  [
                    "$$this"
                  ]
                ]
              }
            ]
          }
        }
      }
    }
  }
])
Run Code Online (Sandbox Code Playgroud)

蒙戈游乐场