3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

MongoDBの重複データをレコードから削除

Posted at

始めに

MongoDBを利用している際に、重複したデータを複数一括で削除する必要があったので、その際に実行したクエリを共有します。やりたいことは単純だったのですが、ドキュメントがあまりなくクエリ構築に悩んだので備忘録として残しておきます。

MongoDBのデータ操作コマンドに関しては、以下のリンクを参照。

Database Commands — MongoDB Manual

実行

前準備

MongoDBに、以下のようにusernameに同じ値を持つユーザが複数登録されてしまっている。この状態の際に、usernameで重複するデータを削除したい。

> db.user.find()
{ _id: ObjectId("619b2dfa75ca1af74dbe6d8d"),
  username: 'taro',
  age: 18 }
{ _id: ObjectId("619b2e0275ca1af74dbe6d8f"),
  username: 'taro',
  age: 18 }
{ _id: ObjectId("619b2e1175ca1af74dbe6d91"),
  username: 'saburo',
  age: 22 }
{ _id: ObjectId("619b2e1875ca1af74dbe6d93"),
  username: 'saburo',
  age: 22 }
{ _id: ObjectId("619b2e1c75ca1af74dbe6d95"),
  username: 'saburo',
  age: 22 }
{ _id: ObjectId("619b2e2e75ca1af74dbe6d97"),
  username: 'siro',
  age: 25 }

重複削除のコマンド

username要素の重複を削除する場合、以下のコマンドを実行する。

> db.user.aggregate([
  { $group:
    { 
    _id: "$username",
    dups: { "$addToSet": "$_id" }, 
    count: { "$sum": 1 } 
    }
  }, 
  { $match: 
    { 
    count: { "$gt": 1 }
    }
  }
]).forEach(function(doc) {
    doc.dups.shift(); 
    db.user.remove({_id : {$in: doc.dups }});
})

実行後再度確認すると、重複が削除されていることが確認できる。

> db.user.find()
{ _id: ObjectId("619b2dfa75ca1af74dbe6d8d"),
  username: 'taro',
  age: 18 }
{ _id: ObjectId("619b2e1875ca1af74dbe6d93"),
  username: 'saburo',
  age: 22 }
{ _id: ObjectId("619b2e2e75ca1af74dbe6d97"),
  username: 'siro',
  age: 25 }

クエリの解説

先ほど実行したクエリの各要素の意味は以下の通り。

> db.user.aggregate([
  { $group: # 同じusernameを持つものでグループ化
    { 
    _id: "$username", # ここに重複を集約したいキーを指定する
    dups: { "$addToSet": "$_id" },  # dupsと言う辞書に重複が発生した_idを格納する。
    count: { "$sum": 1 }  # usernameの出現回数をカウント
    }
  }, 
  { $match: # 上記のクエリで集約した結果に対して条件に合うもののみを抽出
    { 
    count: { "$gt": 1 } # countが2以上(=重複が存在するもの)のみ抽出
    }
  }
]).forEach(function(doc) {
    doc.dups.shift(); # 重複が存在するキーのうち、先頭1つ残すために、先頭の要素を削除対象から除外
    db.user.remove({_id : {$in: doc.dups }}); # キーの配列より一致する_idを持つ要素を削除
})
3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?