Champs imbriqués du projet MongoDB

Mehvish Ashiq 30 janvier 2023
  1. Champs imbriqués du projet MongoDB
  2. Utilisez l’étape d’agrégation $project pour projeter des champs imbriqués dans MongoDB
  3. Utilisez l’étape d’agrégation $unset pour obtenir des champs imbriqués à l’exclusion de ceux spécifiés dans MongoDB
  4. Utiliser une boucle forEach() pour obtenir des champs imbriqués dans MongoDB
  5. Utilisez la méthode mapReduce() pour projeter des champs imbriqués dans MongoDB
Champs imbriqués du projet MongoDB

Aujourd’hui, nous allons apprendre à utiliser les étapes d’agrégation $project et $unset, la boucle forEach() et la méthode mapReduce() pour projeter des champs imbriqués tout en interrogeant des données dans MongoDB.

Champs imbriqués du projet MongoDB

Dans MongoDB, nous pouvons récupérer tous les documents en utilisant la méthode find(), mais que se passe-t-il si nous ne voulons accéder qu’à des champs imbriqués spécifiques. C’est là que nous utilisons la projection.

Nous pouvons projeter des champs imbriqués de différentes manières. Ici, nous allons découvrir les solutions suivantes pour projeter des champs imbriqués.

  1. Utiliser l’étape d’agrégation $project
  2. Utiliser l’étape d’agrégation $unset
  3. Utilisez la boucle forEach()
  4. Utilisez la fonction mapReduce()

Pour apprendre les approches ci-dessus, créons une collection nommée nested contenant un document. Vous pouvez également utiliser la requête ci-dessous pour nous contacter.

Exemple de code :

// MongoDB version 5.0.8

> db.nested.insertOne(
    {
        "name": {
            "first_name": "Mehvish",
            "last_name": "Ashiq",
         },
         "contact": {
            "phone":{"type": "manager", "number": "123456"},
            "email":{ "type": "office", "mail": "delfstack@example.com"}
         },
         "country_name" : "Australien",
         "posting_locations" : [
             {
                 "city_id" : 19398,
                 "city_name" : "Bondi Beach (Sydney)"
             },
             {
                  "city_id" : 31101,
                  "city_name" : "Rushcutters Bay (Sydney)"
             },
             {
                  "city_id" : 31022,
                  "city_name" : "Wolly Creek (Sydney)"
             }
          ],
          "regions" : {
              "region_id" : 796,
              "region_name" : "Australien: New South Wales (Sydney)"
          }
    }
);

Utilisez db.nested.find().pretty(); sur mongo shell pour voir les données insérées.

Utilisez l’étape d’agrégation $project pour projeter des champs imbriqués dans MongoDB

Exemple de code :

// MongoDB version 5.0.8

> var current_location = "posting_locations";
> var project = {};
> project["id"] = "$"+current_location+".city_id";
> project["name"] = "$"+current_location+".city_name";
> project["regions"] = 1;

> var find = {};
> find[current_location] = {"$exists":true};

> db.nested.aggregate([
    { $match : find },
    { $project : project }
]).pretty()

PRODUCTION:

{
        "_id" : ObjectId("62a96d397c7e3688aea26d0d"),
        "regions" : {
                "region_id" : 796,
                "region_name" : "Australien: New South Wales (Sydney)"
        },
        "id" : [
                19398,
                31101,
                31022
        ],
        "name" : [
                "Bondi Beach (Sydney)",
                "Rushcutters Bay (Sydney)",
                "Wolly Creek (Sydney)"
        ]
}

Ici, nous sauvegardons le champ de premier niveau nommé posting_locations dans une variable appelée current_location.

Ensuite, nous utilisons cette variable pour accéder à city_id et city_name et les enregistrons dans l’objet project tout en utilisant la notation entre parenthèses pour créer des propriétés pour l’objet project. De plus, nous sauvegardons le champ regions dans l’objet project["regions"].

Ensuite, nous avons un autre objet nommé find que nous utiliserons dans la méthode aggregate() pour faire correspondre les documents. Dans la méthode aggregate(), on utilise l’étape $match pour faire correspondre les documents et $project pour projeter les champs, qu’ils soient imbriqués ou au premier niveau.

Nous utilisons $project pour spécifier les champs que nous voulons afficher dans la sortie. Nous pouvons utiliser la solution suivante si nous souhaitons projeter uniquement les champs imbriqués spécifiés sans aucune requête de filtre.

Exemple de code :

// MongoDB version 5.0.8

> var current_location = "posting_locations";
> db.nested.aggregate({
    $project: {
         "_id": 0,
         "city_id": "$" + current_location + ".city_id",
         "city_name": "$" + current_location + ".city_name",
         "regions": 1
    }
}).pretty();

PRODUCTION:

{
        "regions" : {
                "region_id" : 796,
                "region_name" : "Australien: New South Wales (Sydney)"
        },
        "city_id" : [
                19398,
                31101,
                31022
        ],
        "city_name" : [
                "Bondi Beach (Sydney)",
                "Rushcutters Bay (Sydney)",
                "Wolly Creek (Sydney)"
        ]
}

Utilisez l’étape d’agrégation $unset pour obtenir des champs imbriqués à l’exclusion de ceux spécifiés dans MongoDB

Exemple de code :

// MongoDB version 5.0.8

> db.nested.aggregate({
        $unset: ["posting_locations.city_id", "contact", "regions", "name", "_id"]
}).pretty()

PRODUCTION:

{
        "country_name" : "Australien",
        "posting_locations" : [
                {
                        "city_name" : "Bondi Beach (Sydney)"
                },
                {
                        "city_name": "Rushcutters Bay (Sydney)"
                },
                {
                        "city_name": "Wolly Creek (Sydney)"
                }
        ]
}

Ici, nous utilisons l’opérateur $unset, qui est utilisé pour supprimer le champ ou le tableau de champs spécifié.

N’oubliez pas que nous utilisons la notation par points pour spécifier les documents intégrés ou le tableau de documents. L’opérateur $unset n’effectue aucune opération si le champ donné n’existe pas.

Lorsque nous utilisons $ pour faire correspondre les éléments d’un tableau, l’opérateur $unset remplace les éléments correspondants par null au lieu de les supprimer du tableau. Ce comportement aide à maintenir la cohérence des positions des éléments et de la taille du tableau.

Utiliser une boucle forEach() pour obtenir des champs imbriqués dans MongoDB

Exemple de code :

// MongoDB version 5.0.8

> var bulk = db.newcollection.initializeUnorderedBulkOp(),
   counter = 0;

> db.nested.find().forEach(function(doc) {
    var document = {};
    document["name"] = doc.name.first_name + " " + doc.name.last_name;
    document["phone"] = doc.contact.phone.number;
    document["mail"] = doc.contact.email.mail;
    bulk.insert(document);
    counter++;
    if (counter % 1000 == 0) {
        bulk.execute();
        bulk = db.newcollection.initializeUnorderedBulkOp();
    }
});

> if (counter % 1000 != 0) { bulk.execute(); }

Vous verrez quelque chose de similaire à ce qui suit.

BulkWriteResult({
        "writeErrors" : [ ],
        "writeConcernErrors" : [ ],
        "nInserted" : 1,
        "nUpserted" : 0,
        "nMatched" : 0,
        "nModified" : 0,
        "nRemoved" : 0,
        "upserted" : [ ]
})

Ensuite, exécutez la commande ci-dessous sur votre shell mongo pour voir les champs projetés.

// MongoDB version 5.0.8

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

PRODUCTION:

{
        "_id" : ObjectId("62a96f2d7c7e3688aea26d0e"),
        "name" : "Mehvish Ashiq",
        "phone" : "123456",
        "mail" : "delfstack@example.com"
}

Pour apprendre cet exemple de code, supposons que nous voulions saisir certains champs imbriqués et les insérer dans une nouvelle collection. Ici, l’insertion des champs transformés en tant que document dans une nouvelle collection peut avoir un impact sur nos opérations en fonction de la taille de la collection imbriquée.

Nous pouvons éviter ce ralentissement des performances d’insertion en utilisant une nouvelle API insertion en masse non ordonnée. Il rationalisera les opérations d’insertion en envoyant en masse et nous donnera des informations en temps réel sur la réussite ou l’échec de l’opération.

Ainsi, nous utilisons l’API bulk insert pour insérer la structure de données souhaitée dans la collection newcollection, où les nouveaux documents seront créés avec la boucle forEach() du curseur de collection imbriqué. Pour créer de nouvelles propriétés, nous utilisons la notation entre crochets.

Pour ce code, nous supposons avoir une grande quantité de données. Ainsi, nous allons envoyer les opérations à un serveur par lots de 1000 pour effectuer l’opération d’insertion en bloc.

En conséquence, cela nous donne de bonnes performances car nous n’envoyons pas chaque requête mais une seule fois pour 1000 requêtes au serveur.

Utilisez la méthode mapReduce() pour projeter des champs imbriqués dans MongoDB

Exemple de code :

// MongoDB version 5.0.8

> function map() {
    for(var i in this.posting_locations) {
         emit({
             "country_id" : this.country_id,
             "city_id" : this.posting_locations[i].city_id,
             "region_id" : this.regions.region_id
         },1);
    }
}

> function reduce(id,docs) {
      return Array.sum(docs);
}

> db.nested.mapReduce(map,reduce,{ out : "map_reduce_output" } )

Maintenant, exécutez la requête suivante pour voir la sortie.

// MongoDB version 5.0.8
> db.map_reduce_output.find().pretty();

PRODUCTION:

{
        "_id" : {
                "country_id" : undefined,
                "city_id" : 19398,
                "region_id" : 796
        },
        "value" : 1
}
{
        "_id" : {
                "country_id" : undefined,
                "city_id" : 31022,
                "region_id" : 796
        },
        "value" : 1
}
{
        "_id" : {
                "country_id" : undefined,
                "city_id" : 31101,
                "region_id" : 796
        },
        "value" : 1
}

Pour cet exemple de code, nous utilisons la fonction mapReduce() pour effectuer une réduction de carte sur tous les documents de la collection imbriquée. Pour cela, nous devons suivre un processus en trois étapes brièvement expliqué ci-dessous.

  • Définissez la fonction map() pour traiter chaque document d’entrée. Dans cette fonction, le mot-clé this fait référence au document en cours de traitement par l’opération de réduction de carte, et la fonction emit() mappe les valeurs données aux clés et les renvoie.
  • Ici, nous définissons la fonction reduce() correspondante, qui est l’endroit réel où l’agrégation des données a lieu. Il prend deux arguments (keys et values) ; notre exemple de code prend les id et docs.

    Rappelons que les éléments de la docs sont renvoyés par la fonction emit() de la méthode map(). A cette étape, la fonction reduce() réduit le tableau docs à la somme de ses valeurs (éléments).

  • Enfin, nous effectuons map-reduce sur tous les documents de la collection imbriquée en utilisant les fonctions map() et reduce(). Nous utilisons out pour enregistrer la sortie dans la collection spécifiée, qui est map_reduce_output dans ce cas.
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