Champs imbriqués du projet MongoDB
- Champs imbriqués du projet MongoDB
-
Utilisez l’étape d’agrégation
$project
pour projeter des champs imbriqués dans MongoDB -
Utilisez l’étape d’agrégation
$unset
pour obtenir des champs imbriqués à l’exclusion de ceux spécifiés dans MongoDB -
Utiliser une boucle
forEach()
pour obtenir des champs imbriqués dans MongoDB -
Utilisez la méthode
mapReduce()
pour projeter des champs imbriqués dans 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.
- Utiliser l’étape d’agrégation
$project
- Utiliser l’étape d’agrégation
$unset
- Utilisez la boucle
forEach()
- 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 fonctionemit()
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
etvalues
) ; notre exemple de code prend lesid
etdocs
.Rappelons que les éléments de la
docs
sont renvoyés par la fonctionemit()
de la méthodemap()
. A cette étape, la fonctionreduce()
réduit le tableaudocs
à 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()
etreduce()
. Nous utilisonsout
pour enregistrer la sortie dans la collection spécifiée, qui estmap_reduce_output
dans ce cas.