Verbinden mehrerer Bedingungen mit dem Lookup-Operator in MongoDB

Mehvish Ashiq 2 Juni 2022
  1. Verbinden Sie mehrere Bedingungen mit dem Operator $lookup in MongoDB
  2. Erstellen Sie eine neue Sammlung und verwenden Sie die Aggregationsphase $group, um mehreren Bedingungen beizutreten
Verbinden mehrerer Bedingungen mit dem Lookup-Operator in MongoDB

Heute werden wir sehen, wie man mehrere Bedingungen mit dem Operator $lookup in MongoDB verbindet. Darüber hinaus werden wir auch einige Beispiele untersuchen, die die Verwendung der Stufe $group und der Aggregationsstufe $unionWidth demonstrieren.

Verbinden Sie mehrere Bedingungen mit dem Operator $lookup in MongoDB

Wenn wir MongoDB 3.6 oder höher haben, können wir den Aggregationsoperator $lookup pipeline verwenden, um mehrere Bedingungen zusammenzuführen.

Dafür haben wir zwei Sammlungen namens users und salaries. Sie können dies auch mit den folgenden Befehlen erstellen.

Beispielcode zum Erstellen von Sammlungen:

> db.createCollection('users')
> db.createCollection('salaries')

Beispielcode zum Einfügen von Dokumenten in die Collection users:

> db.users.insertMany(
    [
        {
            username: 'userone',
            age: 30,
            gender: 'Female',
            city: 'Lahore',
            country: 'Pakistan'
        },
        {
            username: 'usertwo',
            age: 35,
            gender: 'Male',
            city: 'Florida',
            country: 'United States'
        }
    ]
)

Beispielcode zum Einfügen von Dokumenten in die Sammlung salaries:

> db.salaries.insertMany(
    [
        {
            username: 'userone',
            salary: 3000
        },
        {
            username: 'usertwo',
            salary: 5000
        }
    ]
)

Anzeigedaten der Sammlung users:

> db.users.find().pretty()

AUSGANG:

{
        "_id" : ObjectId("628deb40c1e812eeeb311439"),
        "username" : "userone",
        "age" : 30,
        "gender" : "Female",
        "city" : "Lahore",
        "country" : "Pakistan"
}
{
        "_id" : ObjectId("628deb40c1e812eeeb31143a"),
        "username" : "usertwo",
        "age" : 35,
        "gender" : "Male",
        "city" : "Florida",
        "country" : "United States"
}

Anzeigedaten der Collection salaries:

> db.salaries.find().pretty()

AUSGANG:

{
        "_id" : ObjectId("628deb07c1e812eeeb311437"),
        "username" : "userone",
        "salary" : 3000
}
{
        "_id" : ObjectId("628deb07c1e812eeeb311438"),
        "username" : "usertwo",
        "salary" : 5000
}

Nachdem wir die Sammlungen erstellt und Dokumente eingefügt haben, können wir verschiedene Szenarien untersuchen, um mehrere Bedingungen zu verbinden. Beginnen wir mit $lookup.

Verwendung von den $lookup-Aggregations-pipeline-Operator

Beispielcode:

> db.users.aggregate([
    {
        $lookup: {
            from: 'salaries',
            let: {
                user_name: '$username',
                user_salary: 3000
            },
            pipeline: [{
                $match: {
                    $expr: {
                        $and: [
                            { $eq: ['$username', '$$user_name'] },
                            { $gte: ['$salary','$$user_salary'] }
                        ]
                    }
                }
           }],
           as: 'usersalary'
        }
    }
]).pretty()

AUSGANG:

{
        "_id" : ObjectId("628deb40c1e812eeeb311439"),
        "username" : "userone",
        "age" : 30,
        "gender" : "Female",
        "city" : "Lahore",
        "country" : "Pakistan",
        "usersalary" : [
                {
                        "_id" : ObjectId("628deb07c1e812eeeb311437"),
                        "username" : "userone",
                        "salary" : 3000
                }
        ]
}
{
        "_id" : ObjectId("628deb40c1e812eeeb31143a"),
        "username" : "usertwo",
        "age" : 35,
        "gender" : "Male",
        "city" : "Florida",
        "country" : "United States",
        "usersalary" : [
                {
                        "_id" : ObjectId("628deb07c1e812eeeb311438"),
                        "username" : "usertwo",
                        "salary" : 5000
                }
        ]
}

Hier erhalten wir die Dokumente, die zwei Bedingungen erfüllen.

  1. Das Feld Benutzername ist in den Sammlungen users und salaries gleich.
  2. Der Wert des Feldes Gehalt ist grösser oder gleich 3000.

Wir erhalten nur das Dokument, das beide Bedingungen erfüllt. Sie haben vielleicht bemerkt, dass das Benutzergehalt als ein Array von Elementen sichtbar ist, wobei jedes Element ein Dokument der Sammlung salaries ist.

Wir können die Felder $unwind, $addFields und $project verwenden, um die spezifischen Felder aus beiden Sammlungen (users und salaries) abzurufen und ein Dokument zu bilden, wie im folgenden Beispiel gezeigt.

Beispielcode:

> db.users.aggregate([
    {
        $lookup: {
            from: 'salaries',
            let: {
                user_name: '$username',
                user_salary: 3000
            },
            pipeline: [{
                $match: {
                    $expr: {
                        $and: [
                            { $eq: ['$username', '$$user_name'] },
                            { $gte: ['$salary','$$user_salary'] }
                        ]
                    }
                }
           }],
           as: 'usersalary'
        }
    },
    {
        $unwind:'$usersalary'
    },
    {
        $addFields: {
            salary: '$usersalary.salary'
        }
    },
    {
       $project: {
           username: 1,
           salary: 1
       }
    }
]).pretty()

AUSGANG:

{
        "_id" : ObjectId("628deb40c1e812eeeb311439"),
        "username" : "userone",
        "salary" : 3000
}
{
        "_id" : ObjectId("628deb40c1e812eeeb31143a"),
        "username" : "usertwo",
        "salary" : 5000
}

Der Zweck der Verwendung des Operators $unwind besteht darin, ein Array-Feld von Eingabedokumenten in ein Ausgabedokument für jedes Element mit demselben Namen zu zerlegen.

Wenn das Array nur ein Element enthält, flacht der Stufenoperator $unwind das Objekt ab, das das Element selbst ist. Die $addFields verbinden das salary-Feld von einem Objekt oder Array mit der Root-Ebene des Dokuments.

Konzentrieren wir uns auf den Grund für die Verwendung der Filterstufe $project, bevor wir ihre Verwendung im oben angegebenen Beispiel verstehen. Wenn wir das $project nicht verwenden, erhalten wir das salary-Feld auf der Root-Ebene des Dokuments und das usersalary-Objekt, was unnötig ist.

Hier verwenden wir die Filterphase $project und geben an, welche Felder in der Ausgabe enthalten sein sollen.

Wir können die unten angegebene alternative Lösung verwenden, wenn die Projektanforderungen die Verwendung von $unwind, $addFields, $project einschränken.

Beispielcode:

> db.users.aggregate([
    {
        $lookup: {
            from: 'salaries',
            let: {
                user_name: '$username',
                user_salary: 3000
            },
            pipeline: [{
                $match: {
                    $expr: {
                        $and: [
                            { $eq: ['$username', '$$user_name'] },
                            { $gte: ['$salary','$$user_salary'] }
                        ]
                    }
                }
           }],
           as: 'usersalary'
        }
    },
       {
          $replaceRoot: {
             newRoot: {
                $mergeObjects:[
                   {
                      $arrayElemAt: [
                         "$usersalary", 0
                      ]
                   },
                   {
                      salary: "$$ROOT.salary"
                   }
                ]
             }
          }
       }
    ]
).pretty()

AUSGANG:

{
        "_id" : ObjectId("628deb07c1e812eeeb311437"),
        "username" : "userone",
        "salary" : 3000
}
{
        "_id" : ObjectId("628deb07c1e812eeeb311438"),
        "username" : "usertwo",
        "salary" : 5000
}

Wir verwenden das Feld let (optional), um die Werte von Feldern Variablen zuzuweisen. Wir greifen auf diese Variablen in der pipeline-Phase zu, wo wir die pipeline angeben, die auf verschiedenen Sammlungen ausgeführt werden soll.

Beachten Sie, dass wir auch die Stufe $match verwenden, um den Auswertungsabfrageoperator namens $expr zu nutzen, der den Wert von Feldern vergleicht.

Außerdem ist $replaceRoot die letzte Aggregations-pipeline-Stufe in der pipeline, wo wir den Operator $mergeObjects verwenden, um die $lookup-Ausgabe mit dem Teil des $$ROOT-Dokuments zusammenzuführen .

Wir haben nur den Operator $and verwendet, um die Bedingungen zu verbinden. Sie können auch $or oder beide Operatoren verwenden.

Erstellen Sie eine neue Sammlung und verwenden Sie die Aggregationsphase $group, um mehreren Bedingungen beizutreten

Beispielcode:

> db.users_salaries.insertMany(
    db.users.find({}, {"_id": 0})
    .toArray()
    .concat(db.salaries.find({}, {"_id": 0}).toArray())
)

db.users_salaries.aggregate([
    { "$group": {
        "_id": { "username": "$username" },
        "salary": { "$push": "$salary" }
    }}
])

AUSGANG:

{ "_id" : { "username" : "userone" }, "salary" : [ 3000 ] }
{ "_id" : { "username" : "usertwo" }, "salary" : [ 5000 ] }

Für dieses Codebeispiel erstellen wir eine neue Sammlung mit dem Namen users_salaries, führen zwei Sammlungen mit den Namen users und salaries zusammen und fügen diese Dokumente dann in die neu erstellte Sammlung ein. Gruppieren Sie dann nach dem Benutzernamen, um die gewünschte Ausgabe zu erhalten.

Wir können auch die gleiche Ausgabe (wie oben angegeben) erhalten, ohne eine neue Sammlung zu erstellen. Dafür verwenden wir die Aggregationsstufe $unionWith, die eine Vereinigung für zwei Sammlungen durchführt.

Beispielcode:

> db.users.aggregate([
  { $set: { username: "$username" } },
  { $unionWith: {
    coll: "salaries",
    pipeline: [{ $set: { salary: "$salary" } }]
  }},
  { $group: {
    _id: { username: "$username"},
     "salary": { "$push": "$salary" }
  }}
])

AUSGANG:

{ "_id" : { "username" : "userone" }, "salary" : [ 3000 ] }
{ "_id" : { "username" : "usertwo" }, "salary" : [ 5000 ] }
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

Verwandter Artikel - MongoDB Operator