MongoDB
 Computer >> コンピューター >  >> プログラミング >> MongoDB

MongoDBの単一クエリで$groupとdistinct(重複排除)を同時に実行する方法

MongoDBでは、集計パイプライン(aggregate)の $group ステージに $addToSet 演算子を組み合わせることで、単一のクエリ内で「グループ化」と「distinct(重複値の抽出)」を同時に実行できます。本記事では、学生データを例に、その具体的な手順を解説します。

サンプルコレクションの作成

まず、insertOne() メソッドを使って、ドキュメントを格納したコレクションを作成します。

> db.demo16.insertOne({
...     "StudentName" : "Chris",
...     "StudentSection" : "A",
...     "StudentAge" : 23,
...     "StudentMarks" : 47
... }
... );
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5e13827455d0fc6657d21f07")
}
> db.demo16.insertOne({
...     "StudentName" : "Bob",
...     "StudentSection" : "B",
...     "StudentAge" : 21,
...     "StudentMarks" : 85
... }
... );
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5e13827555d0fc6657d21f08")
}
> db.demo16.insertOne({
...     "StudentName" : "Carol",
...     "StudentSection" : "A",
...     "StudentAge" : 26,
...     "StudentMarks" : 97
... }
... );
{
    "acknowledged" : true,
    "insertedId" : ObjectId("5e13827655d0fc6657d21f09")
}

上記のコレクションには、3名の学生データが登録されました。ChrisとCarolは同じセクション「A」に所属しており、この後の重複排除の動作を確認するのに適したサンプルです。

find()メソッドで全ドキュメントを確認

登録したすべてのドキュメントを表示するには、find() メソッドを使用します。

> db.demo16.find().pretty();

実行すると、以下の出力が得られます。

{
    "_id" : ObjectId("5e13827455d0fc6657d21f07"),
    "StudentName" : "Chris",
    "StudentSection" : "A",
    "StudentAge" : 23,
    "StudentMarks" : 47
}
{
    "_id" : ObjectId("5e13827555d0fc6657d21f08"),
    "StudentName" : "Bob",
    "StudentSection" : "B",
    "StudentAge" : 21,
    "StudentMarks" : 85
}
{
    "_id" : ObjectId("5e13827655d0fc6657d21f09"),
    "StudentName" : "Carol",
    "StudentSection" : "A",
    "StudentAge" : 26,
    "StudentMarks" : 97
}

$groupと$addToSetでグループ化と重複排除を同時に実行

それでは、グループ化とdistinct操作を1つのクエリでまとめて実行してみましょう。ポイントは、_idnull に設定して全ドキュメントを1つのグループとして扱い、各フィールドに対して $addToSet(重複しない値の配列を作成)、$min(最小値)、$max(最大値)を適用することです。

> db.demo16.aggregate([{
...     $group : {
...         _id : null,
...         StudentName : { $addToSet : "$StudentName" },
...         StudentSection : { $addToSet : "$StudentSection" },
...         StudentMinimumAge : { $min : "$StudentAge" },
...         StudentMaximumAge : { $max : "$StudentAge" },
...         StudentMinimumMarks: { $min : "$StudentMarks" },
...         StudentMaximumMarks : { $max : "$StudentMarks" }
... }
... }]).pretty();

このクエリを実行すると、以下のような結果が出力されます。

{
    "_id" : null,
    "StudentName" : [
        "Carol",
        "Bob",
        "Chris"
    ],
    "StudentSection" : [
        "B",
        "A"
    ],
    "StudentMinimumAge" : 21,
    "StudentMaximumAge" : 26,
    "StudentMinimumMarks" : 47,
    "StudentMaximumMarks" : 97
}

結果のポイント

  • StudentName: 重複のない学生名のリストが配列として返されます(distinct相当の動作)。
  • StudentSection: ChrisとCarolが同じ「A」セクションでも、「A」「B」はそれぞれ1回だけ出力され、重複が自動的に除去されます。これが $addToSet の働きです。
  • 年齢・点数: $min$max により、全体の中から最小・最大の値がそれぞれ集計されています。

このように、$group ステージ内で複数の累積演算子($addToSet$min$maxなど)を組み合わせれば、SQLでいうGROUP BYとDISTINCTを別々のクエリで実行する必要はなく、MongoDBではたった1つのaggregateクエリで効率的に処理できます。

  1. MySQLのCOUNT()とDISTINCTを組み合わせて重複行を除いた件数を取得する方法

    はい、COUNT()とDISTINCTを組み合わせることで、重複を除外した行数だけをカウントして表示することができます。 MySQLでは、COUNT()関数単体で使用するとテーブル内のすべての行がカウントされますが、DISTINCTキーワードを組み合わせることで、一意な値を持つ行のみを集計対象にできます。データ分析やレポート作成の際に、重複データを排除した正確な件数が必要になる場面は多く、この組み合わせは非常に実用的です。 COUNT(DISTINCT ...) の基本構文 構文は以下の通りです。 SELECT COUNT(DISTINCT yourColumnName) AS anyVar

  2. MySQLでIdごとに重複を除外してGROUP_CONCATするクエリの書き方

    はじめにMySQLでは、テーブル内に同じIdとNameの組み合わせが重複して登録されているケースがあります。このような場合、DISTINCTで重複行を除外したうえでGROUP_CONCAT()を適用すれば、Idによって区別された一意な値だけを連結できます。本記事では、実際にテーブルを作成し、データを挿入してから、Idごとに重複を除外したGROUP_CONCATを実行するまでの手順を具体的に解説します。サンプルテーブルの作成まず、以下のCREATE TABLE文でテーブルを作成します。mysql> create table DemoTable ( Id int, Name