MongoDB を使用して 2つのコレクションを 1つのコレクションに結合する

Mehvish Ashiq 2023年1月30日
  1. MongoDB を使用して、2つのコレクションを 1つのコレクションに結合する
  2. $lookup 集計ステージを使用して、2つのコレクションを 1つに結合する
  3. pipeline 演算子を使用して、指定された条件に基づいて 2つのコレクションを 1つに結合する
  4. 結果のドキュメントに添付する前に、$unwind 演算子を使用してフラットアレイにする
  5. 集計クエリの $project フィルタステージを使用して、2つのコレクションを 1つに結合する
  6. Compass(MongoDB のグラフィカルインターフェイス)を使用して 2つのコレクションに参加する
MongoDB を使用して 2つのコレクションを 1つのコレクションに結合する

今日は、$lookup 集計ステージ、pipeline および $unwind 演算子、$project フィルターステージ、および MongoDB Compass を使用して、2つのコレクションを 1つのコレクションに結合します。

MongoDB を使用して、2つのコレクションを 1つのコレクションに結合する

MongoDB を使用して、2つのコレクションを 1つのコレクションに結合するためのさまざまなアプローチがあります。それらのいくつかを以下に示します。これについては、このチュートリアルで説明します。

  1. $lookup 集計ステージを使用して、2つのコレクションを結合します
  2. pipeline 演算子を使用して、指定された条件に基づいて 2つのコレクションを結合します
  3. $unwind 演算子を使用して、結果のドキュメントに添付する前にアレイをフラット化します
  4. 集計クエリで $project フィルターステージを使用して、2つのコレクションを結合します
  5. コンパス(MongoDB のグラフィカルインターフェイス)を使用して 2つのコレクションを結合します

上記のすべてのシナリオでは、ドキュメント(MySQL のレコードと同じ)が入力された 2つのコレクション(MySQL のテーブルと同じ)を含むデータベースが必要です。次のクエリを使用してこれを実行しました。あなたもそうすることができます。

users データベースに存在する usersInformationuserAddress という名前の 2つのコレクションを作成します。さらに、次のようにドキュメントを入力します。

データベースとコレクションを作成します。

> use users
> db.createCollection('userInformation')
> db.createCollection('userAddress')

userInformation コレクションに 2つのドキュメントを入力します。

> db.userInformation.insertMany(
    [
        {
            fullname: 'Mehvish Ashiq',
            age: 30,
            gender: 'Female',
            nationality: 'Pakistani'
        },
        {
            fullname: 'James Daniel',
            age: 45,
            sex: 'male',
            nationality: 'Canadian'
        }
    ]
)

userAddress コレクションに 2つのドキュメントを入力します。

> db.userAddress.insertMany(
    [
        {
            fullname: 'Mehvish Ashiq',
            block_number: 22,
            street: 'Johar Town Street',
            city: 'Lahore'
        },
        {
            fullname: 'James Daniel',
            block_number: 30,
            street: 'Saint-Denis Street',
            city: 'Montreal'
        }
    ]
)

insertMany() 関数を使用して、複数のドキュメントを挿入します。これで、以下のコマンドを使用して、両方のコレクションのデータを確認できます。

次のコードスニペットでは、pretty() メソッドがクリーンでフォーマットされた出力を示しています。これはシェルで簡単に理解できます。

userInformation からのドキュメントを表示します。

> db.userInformation.find().pretty()

出力:

{
        "_id" : ObjectId("628bc4a45c544feccff5a566"),
        "fullname" : "Mehvish Ashiq",
        "age" : 30,
        "gender" : "Female",
        "nationality" : "Pakistani"
}
{
        "_id" : ObjectId("628bc4a45c544feccff5a567"),
        "fullname" : "James Daniel",
        "age" : 45,
        "sex" : "male",
        "nationality" : "Canadian"
}

userAddress からドキュメントを表示します。

> db.userAddress.find().pretty()

出力:

{
        "_id" : ObjectId("628bc4ae5c544feccff5a568"),
        "fullname" : "Mehvish Ashiq",
        "block_number" : 22,
        "street" : "Johar Town Street",
        "city" : "Lahore"
}
{
        "_id" : ObjectId("628bc4ae5c544feccff5a569"),
        "fullname" : "James Daniel",
        "block_number" : 30,
        "street" : "Saint-Denis Street",
        "city" : "Montreal"
}

$lookup 集計ステージを使用するには、両方のコレクションが同じデータベースに存在する必要があります。両方のコレクションの準備ができたら、さまざまなクエリを使用して、シナリオに応じて両方のコレクションのデータを結合できます。

$lookup 集計ステージを使用して、2つのコレクションを 1つに結合する

サンプルコード:

> db.userInformation.aggregate([
    { $lookup:
        {
           from: 'userAddress',
           localField: 'fullname',
           foreignField: 'fullname',
           as: 'address'
        }
    }
]).pretty();

出力:

{
        "_id" : ObjectId("628bc4a45c544feccff5a566"),
        "fullname" : "Mehvish Ashiq",
        "age" : 30,
        "gender" : "Female",
        "nationality" : "Pakistani",
        "address" : [
                {
                        "_id" : ObjectId("628bc4ae5c544feccff5a568"),
                        "fullname" : "Mehvish Ashiq",
                        "block_number" : 22,
                        "street" : "Johar Town Street",
                        "city" : "Lahore"
                }
        ]
}
{
        "_id" : ObjectId("628bc4a45c544feccff5a567"),
        "fullname" : "James Daniel",
        "age" : 45,
        "sex" : "male",
        "nationality" : "Canadian",
        "address" : [
                {
                        "_id" : ObjectId("628bc4ae5c544feccff5a569"),
                        "fullname" : "James Daniel",
                        "block_number" : 30,
                        "street" : "Saint-Denis Street",
                        "city" : "Montreal"
                }
        ]
}

MongoDB データベースでは、$lookupaggregate stageが他のコレクションとの左外部結合を実行し、結合されたドキュメントから情報(データ)をフィルタリングします。たとえば、クエリを使用して、すべてのユーザーの情報とそのアドレスを取得します。

$lookup 関数は 4つのフィールドを受け入れます。最初は from フィールドで、他のコレクションと結合されることになっているコレクションを指定します。

2 番目は localField フィールドです。これは、from フィールドで指定されたコレクションの入力ドキュメントの属性(フィールド)の 1つです。

これは、コレクションのドキュメントから localField から foreignField への照合を実行するために使用されます。

同様に、foreignField という名前の 3 番目のフィールドも、コレクションのドキュメントから foreignField から localField への等価一致を実行します。

4 番目のフィールド as に新しいアレイの名前を書き込みます。 $lookup 集計ステージについては、次の説明を参照してください。

mongodb を使用して 2つのコレクションを 1つのコレクションに結合します-ルックアップステージの説明

pipeline 演算子を使用して、指定された条件に基づいて 2つのコレクションを 1つに結合する

サンプルコード:

> db.userInformation.aggregate([{
    $lookup:{
        from: 'userAddress',
        let: {full_name: '$fullname'},
        pipeline: [{
            $match: {
                $expr: {
                    $eq: ['$fullname', '$$full_name']
                }
             }
       }],
       as: 'addressInfo'
    }
}]).pretty()

出力:

{
        "_id" : ObjectId("628bc4a45c544feccff5a566"),
        "fullname" : "Mehvish Ashiq",
        "age" : 30,
        "gender" : "Female",
        "nationality" : "Pakistani",
        "addressInfo" : [
                {
                        "_id" : ObjectId("628bc4ae5c544feccff5a568"),
                        "fullname" : "Mehvish Ashiq",
                        "block_number" : 22,
                        "street" : "Johar Town Street",
                        "city" : "Lahore"
                }
        ]
}
{
        "_id" : ObjectId("628bc4a45c544feccff5a567"),
        "fullname" : "James Daniel",
        "age" : 45,
        "sex" : "male",
        "nationality" : "Canadian",
        "addressInfo" : [
                {
                        "_id" : ObjectId("628bc4ae5c544feccff5a569"),
                        "fullname" : "James Daniel",
                        "block_number" : 30,
                        "street" : "Saint-Denis Street",
                        "city" : "Montreal"
                }
        ]
}

特定の条件に基づいて 2つのコレクションを結合する場合(MySQL で WHERE 句を使用するのと同じように)、$lookuppipeline 演算子を使用できます。

たとえば、userAddressfullnameuserInformationfullname と等しいコレクションに参加しています。

結果のドキュメントに添付する前に、$unwind 演算子を使用してフラットアレイにする

サンプルコード:

> db.userInformation.aggregate([
    { $lookup:
        {
           from: 'userAddress',
           localField: 'fullname',
           foreignField: 'fullname',
           as: 'address'
        }
    },
    {
       $unwind: '$address'
    }
]).pretty();

出力:

{
        "_id" : ObjectId("628bc4a45c544feccff5a566"),
        "fullname" : "Mehvish Ashiq",
        "age" : 30,
        "gender" : "Female",
        "nationality" : "Pakistani",
        "address" : {
                "_id" : ObjectId("628bc4ae5c544feccff5a568"),
                "fullname" : "Mehvish Ashiq",
                "block_number" : 22,
                "street" : "Johar Town Street",
                "city" : "Lahore"
        }
}
{
        "_id" : ObjectId("628bc4a45c544feccff5a567"),
        "fullname" : "James Daniel",
        "age" : 45,
        "sex" : "male",
        "nationality" : "Canadian",
        "address" : {
                "_id" : ObjectId("628bc4ae5c544feccff5a569"),
                "fullname" : "James Daniel",
                "block_number" : 30,
                "street" : "Saint-Denis Street",
                "city" : "Montreal"
        }
}

$unwind 演算子は、結果のドキュメントにアタッチする前に、アレイをフラット化するだけです。 $unwind 演算子の基本的な違いは、単一の要素を持つ配列を、要素自体であるフラット化されたオブジェクトに変換することです。

この要素の名前は変更されないことに注意してください。これは、要素が配列の形式であった場合と同じになります。

$unwind 演算子を使用して、または使用せずに上記のクエリを実行し、address フィールドを確認します。

集計クエリの $project フィルタステージを使用して、2つのコレクションを 1つに結合する

$project を使用してコレクションに参加する前に、その重要性を理解しましょう。たとえば、userAddress という名前のコレクション全体を userInformation に結合したくない場合は、city フィールドと street フィールドのみを結合する必要があります。

その場合、$addFields ステージを使用する必要があります。このステージを使用して、任意のフィールドまたは複数のフィールドをアレイ/オブジェクトからドキュメントのルートレベルに結合/割り当てます。

したがって、次のクエリを実行して、userAddress コレクションから citystreet を取得します。

サンプルコード:

> db.userInformation.aggregate([
    { $lookup:
        {
           from: 'userAddress',
           localField: 'fullname',
           foreignField: 'fullname',
           as: 'address'
        }
    },
    {
       $unwind: '$address'
    },
    {
       $addFields: {
           street: '$address.street',
           city: '$address.city'
       }
    }
]).pretty();

出力:

{
        "_id" : ObjectId("628bc4a45c544feccff5a566"),
        "fullname" : "Mehvish Ashiq",
        "age" : 30,
        "gender" : "Female",
        "nationality" : "Pakistani",
        "address" : {
                "_id" : ObjectId("628bc4ae5c544feccff5a568"),
                "fullname" : "Mehvish Ashiq",
                "block_number" : 22,
                "street" : "Johar Town Street",
                "city" : "Lahore"
        },
        "street" : "Johar Town Street",
        "city" : "Lahore"
}
{
        "_id" : ObjectId("628bc4a45c544feccff5a567"),
        "fullname" : "James Daniel",
        "age" : 45,
        "sex" : "male",
        "nationality" : "Canadian",
        "address" : {
                "_id" : ObjectId("628bc4ae5c544feccff5a569"),
                "fullname" : "James Daniel",
                "block_number" : 30,
                "street" : "Saint-Denis Street",
                "city" : "Montreal"
        },
        "street" : "Saint-Denis Street",
        "city" : "Montreal"
}

上記の出力に注意深く焦点を合わせます。通り都市を取得していますか?はい、ドキュメントのルートレベルで streetcity を取得していますが、現在必要のない address オブジェクトもあります。

ここで、$project フィルターステージが登場します。結果のドキュメントに含める必要のあるフィールドを指定します。

理解を深めるには、次のクエリを参照してください。

サンプルコード:

> db.userInformation.aggregate([
    { $lookup:
        {
           from: 'userAddress',
           localField: 'fullname',
           foreignField: 'fullname',
           as: 'address'
        }
    },
    {
       $unwind: '$address'
    },
    {
       $addFields: {
           street: '$address.street',
           city: '$address.city'
       }
    },
    {
       $project: {
           fullname: 1,
           age: 1,
           gender: 1,
           street: 1,
           city: 1
       }
    }
]).pretty();

出力:

{
        "_id" : ObjectId("628bc4a45c544feccff5a566"),
        "fullname" : "Mehvish Ashiq",
        "age" : 30,
        "gender" : "Female",
        "street" : "Johar Town Street",
        "city" : "Lahore"
}
{
        "_id" : ObjectId("628bc4a45c544feccff5a567"),
        "fullname" : "James Daniel",
        "age" : 45,
        "street" : "Saint-Denis Street",
        "city" : "Montreal"
}

ご覧のとおり、現在 address オブジェクトはありませんが、その 2つのフィールド(streetcity)がドキュメントのルートレベルに割り当てられています。

Compass(MongoDB のグラフィカルインターフェイス)を使用して 2つのコレクションに参加する

グラフィカルインターフェイスを使用した集計は簡単です。 $lookup 集計段階では、次の手順に従うだけで済みます。

  1. MongoDBCompass を開き、サーバーに接続します。

  2. 必要に応じて、新しいデータベースと 2つのコレクションを作成します。Mongo シェルを使用して作成したものと同じデータベースとコレクションを使用します。

  3. 次のように表示されるコレクションを開きます。

    mongodb を使用して 2つのコレクションを 1つのコレクションに結合します-コンパスオープンコレクション

  4. プロジェクトの要件に従ってステージを追加します。 $lookup 集計ステージを追加します。 $lookup フィールドを更新して、右側に目的の結果を確認してください。

    mongodb を使用して 2つのコレクションを 1つのコレクションに結合します-コンパスはルックアップステージを追加します

著者: Mehvish Ashiq
Mehvish Ashiq avatar Mehvish Ashiq avatar

Mehvish Ashiq is a former Java Programmer and a Data Science enthusiast who leverages her expertise to help others to learn and grow by creating interesting, useful, and reader-friendly content in Computer Programming, Data Science, and Technology.

LinkedIn GitHub Facebook

関連記事 - MongoDB Collection

関連記事 - MongoDB Join