Campos anidados del proyecto MongoDB
- Campos anidados del proyecto MongoDB
-
Utilice la etapa de agregación
$project
para proyectar campos anidados en MongoDB -
Use la etapa de agregación
$unset
para 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 clavethis
se 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 (claves
yvalores
); nuestro ejemplo de código tomaid
ydocs
.Recuerda que los elementos de los
docs
son devueltos por la funciónemit()
del métodomap()
. En este paso, la funciónreduce()
reduce la matrizdocs
a la suma de sus valores (elementos). -
Finalmente, realizamos map-reduce en todos los documentos de la colección
anidada
usando las funcionesmap()
yreduce()
. Usamosout
para guardar la salida en la colección especificada, que esmap_reduce_output
en este caso.