Пн go удаление дубликатов в массиве объектов на основе поля - PullRequest
0 голосов
/ 31 марта 2020

Новичок в пн go, нашел много примеров удаления дубликатов из массивов строк с использованием структуры агрегации, но мне интересно, если возможно, удалить дубликаты из массива объектов на основе поля в объекте. Например,

{
"_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"
    }
]
}

Выбор первого / любого объекта с заданным идентификатором работает. Просто хочу, чтобы в конечном итоге с одним на идентификатор. Это выполнимо в структуре агрегации? Или даже вне структуры агрегации, просто ищите чистый способ сделать это. Нужно делать подобные вещи во многих документах в коллекции, что кажется хорошим вариантом использования для структуры агрегации, но, как я уже говорил, newb ie здесь ... спасибо.

Ответы [ 2 ]

1 голос
/ 31 марта 2020

Ну, вы можете получить желаемый результат двумя способами.

Класси c

Свести - Удалить дубликаты (выбрать первое вхождение) - Группировать по

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"
      }
    }
  }
])

MongoPlayground

Современный

Нам нужно использовать оператор $ Reduce .

Псевдокод:

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

db.collection.aggregate([
  {
    $addFields: {
      values: {
        $reduce: {
          input: "$values",
          initialValue: [],
          in: {
            $concatArrays: [
              "$$value",
              {
                $cond: [
                  {
                    $in: [
                      "$$this.id",
                      "$$value.id"
                    ]
                  },
                  [],
                  [
                    "$$this"
                  ]
                ]
              }
            ]
          }
        }
      }
    }
  }
])

MongoPlayground

1 голос
/ 31 марта 2020

Вы можете использовать $ уменьшить , Попробуйте запрос ниже:

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"]] }
            ]
          }
        }
      }
    }
  }
]);

Тест: MongoDB-Playground

...