Campos anidados del proyecto MongoDB
- Campos anidados del proyecto MongoDB
-
Utilice la etapa de agregación
$projectpara proyectar campos anidados en MongoDB -
Use la etapa de agregación
$unsetpara obtener campos anidados que excluyan los especificados en MongoDB -
Utilice un bucle
forEach()para obtener campos anidados en MongoDB -
Utilice el método
mapReduce()para proyectar campos anidados en MongoDB
Hoy aprenderemos a usar las etapas de agregación $project y $unset, el ciclo forEach() y el método mapReduce() para proyectar campos anidados mientras consultamos datos en MongoDB.
Campos anidados del proyecto MongoDB
En MongoDB, podemos recuperar todos los documentos utilizando el método find(), pero ¿qué pasa si solo queremos acceder a campos anidados específicos? Aquí es donde usamos la proyección.
Podemos proyectar campos anidados de varias maneras. Aquí aprenderemos sobre las siguientes soluciones para proyectar campos anidados.
- Usa la etapa de agregación
$project - Utilice la etapa de agregación
$unset - Usa el ciclo
forEach() - Usa la función
mapReduce()
Para aprender los enfoques anteriores, creemos una colección llamada anidada que contenga un documento. También puede usar la consulta que se proporciona a continuación para hacer un seguimiento con nosotros.
Código de ejemplo:
// 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)"
}
}
);
Utilice db.nested.find().pretty(); en mongo shell para ver los datos insertados.
Utilice la etapa de agregación $project para proyectar campos anidados en MongoDB
Código de ejemplo:
// 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()
Producción :
{
"_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)"
]
}
Aquí, guardamos el campo de primer nivel llamado ubicaciones_de_publicación en una variable llamada ubicación_actual.
Luego, usamos esa variable para acceder a city_id y city_name y los guardamos en el objeto project mientras usamos la notación de paréntesis para crear propiedades para el objeto project. Además, guardamos el campo regions en el objeto project["regions"].
A continuación, tenemos otro objeto llamado find que usaremos en el método aggregate() para hacer coincidir los documentos. En el método aggregate(), utilizamos la etapa $match para hacer coincidir los documentos y $project para proyectar los campos, ya sean anidados o de primer nivel.
Usamos $project para especificar qué campos queremos mostrar en la salida. Podemos usar la siguiente solución si estamos interesados en proyectar los campos anidados especificados solo sin ninguna consulta de filtro.
Código de ejemplo:
// 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();
Producción :
{
"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)"
]
}
Use la etapa de agregación $unset para obtener campos anidados que excluyan los especificados en MongoDB
Código de ejemplo:
// MongoDB version 5.0.8
> db.nested.aggregate({
$unset: ["posting_locations.city_id", "contact", "regions", "name", "_id"]
}).pretty()
Producción :
{
"country_name" : "Australien",
"posting_locations" : [
{
"city_name" : "Bondi Beach (Sydney)"
},
{
"city_name": "Rushcutters Bay (Sydney)"
},
{
"city_name": "Wolly Creek (Sydney)"
}
]
}
Aquí, usamos el operador $unset, que se usa para eliminar el campo especificado o la matriz de campos.
Recuerde que usamos la notación de puntos para especificar los documentos incrustados o la matriz de documentos. El operador $unset no realiza ninguna operación si el campo dado no existe.
Cuando usamos $ para hacer coincidir los elementos de una matriz, el operador $unset reemplaza los elementos coincidentes con null en lugar de eliminarlos de la matriz. Este comportamiento ayuda a mantener consistentes las posiciones de los elementos y el tamaño de la matriz.
Utilice un bucle forEach() para obtener campos anidados en MongoDB
Código de ejemplo:
// 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(); }
Verás algo similar a lo siguiente.
BulkWriteResult({
"writeErrors" : [ ],
"writeConcernErrors" : [ ],
"nInserted" : 1,
"nUpserted" : 0,
"nMatched" : 0,
"nModified" : 0,
"nRemoved" : 0,
"upserted" : [ ]
})
A continuación, ejecute el siguiente comando en su mongo shell para ver los campos proyectados.
// MongoDB version 5.0.8
> db.newcollection.find().pretty();
Producción :
{
"_id" : ObjectId("62a96f2d7c7e3688aea26d0e"),
"name" : "Mehvish Ashiq",
"phone" : "123456",
"mail" : "delfstack@example.com"
}
Para aprender este código de ejemplo, supongamos que queremos tomar ciertos campos anidados e insertarlos en una nueva colección. Aquí, insertar los campos transformados como un documento en una nueva colección puede afectar nuestras operaciones en función del tamaño de la colección anidada.
Podemos evitar este rendimiento de inserción lento mediante el uso de una nueva API desordenada inserción masiva. Agilizará las operaciones de inserción mediante el envío masivo y nos dará retroalimentación en tiempo real sobre si la operación tuvo éxito o falló.
Por lo tanto, estamos utilizando la API de inserción masiva para insertar la estructura de datos deseada en la colección nueva colección, donde los nuevos documentos se crearán con el bucle forEach() del cursor de la colección anidada. Para crear nuevas propiedades, usamos la notación de paréntesis.
Para este código, asumimos que tenemos una gran cantidad de datos. Entonces, enviaremos las operaciones a un servidor en lotes de 1000 para realizar la operación de inserción masiva.
Como resultado, nos brinda un buen rendimiento porque no enviamos cada solicitud sino solo una vez por cada 1000 solicitudes al servidor.
Utilice el método mapReduce() para proyectar campos anidados en MongoDB
Código de ejemplo:
// 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" } )
Ahora, ejecute la siguiente consulta para ver el resultado.
// MongoDB version 5.0.8
> db.map_reduce_output.find().pretty();
Producción :
{
"_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
}
Para este código de ejemplo, usamos la función mapReduce() para realizar map-reduce en todos los documentos de la colección anidada. Para eso, tenemos que seguir un proceso de tres pasos que se explica brevemente a continuación.
-
Defina la función
map()para procesar cada documento de entrada. En esta función, la palabra clavethisse refiere al documento actual que está siendo procesado por la operación map-reduce, y la funciónemit()asigna los valores dados a las claves y los devuelve. -
Aquí, definimos la función
reduce()correspondiente, que es el lugar real donde se lleva a cabo la agregación de datos. Toma dos argumentos (clavesyvalores); nuestro ejemplo de código tomaidydocs.Recuerda que los elementos de los
docsson devueltos por la funciónemit()del métodomap(). En este paso, la funciónreduce()reduce la matrizdocsa la suma de sus valores (elementos). -
Finalmente, realizamos map-reduce en todos los documentos de la colección
anidadausando las funcionesmap()yreduce(). Usamosoutpara guardar la salida en la colección especificada, que esmap_reduce_outputen este caso.
