Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
MongoDB Branding Shape
Click here >
Docs Menu

Guardar datos en MongoDB Atlas - Funciones

Los ejemplos en esta página demuestran cómo usar la query API de MongoDB en una función para insertar, actualizar y borrar datos en tu clúster de Atlas.

Nota

Federated data sources do not support write operations.

Los ejemplos de esta página utilizan una colección llamada store.items que modela varios artículos disponibles para su compra en una tienda en línea. Cada artículo tiene un name, un inventario quantity y una matriz de clientes reviews.

El esquema JSON para store.items
{
"title": "Item",
"required": ["_id", "name", "quantity", "reviews"],
"properties": {
"_id": { "bsonType": "objectId" },
"name": { "bsonType": "string" },
"quantity": { "bsonType": "int" },
"reviews": {
"bsonType": "array",
"items": {
"bsonType": "object",
"required": ["username", "comment"],
"properties": {
"username": { "bsonType": "string" },
"comment": { "bsonType": "string" }
}
}
}
}
}

Para usar un code snippet en una función, primero debes crear una instancia de un handle de colección de MongoDB:

exports = function() {
const mongodb = context.services.get("mongodb-atlas");
const itemsCollection = mongodb.db("store").collection("items");
const purchasesCollection = mongodb.db("store").collection("purchases");
// ... paste snippet here ...
}

Las operaciones de inserción toman uno o más documentos y los añaden a una colección de MongoDB.

Devuelven documentos que describen los resultados de la operación.

Puedes insertar un solo documento utilizando el método collection.insertOne().

El siguiente Function snippet inserta un documento de elemento único en la colección items:

const newItem = {
"name": "Plastic Bricks",
"quantity": 10,
"category": "toys",
"reviews": [{ "username": "legolover", "comment": "These are awesome!" }]
};
itemsCollection.insertOne(newItem)
.then(result => console.log(`Successfully inserted item with _id: ${result.insertedId}`))
.catch(err => console.error(`Failed to insert item: ${err}`))

Puedes insertar varios documentos al mismo tiempo utilizando el collection.insertMany() método.

El siguiente Function snippet inserta varios documentos de ítems en la colección items:

const doc1 = { "name": "basketball", "category": "sports", "quantity": 20, "reviews": [] };
const doc2 = { "name": "football", "category": "sports", "quantity": 30, "reviews": [] };
return itemsCollection.insertMany([doc1, doc2])
.then(result => {
console.log(`Successfully inserted ${result.insertedIds.length} items!`);
return result
})
.catch(err => console.error(`Failed to insert documents: ${err}`))

Las operaciones de actualización buscan documentos existentes en una colección de MongoDB y modifican sus datos. Se utiliza la sintaxis de consulta estándar de MongoDB para especificar qué documentos actualizar y los operadores de actualización para describir los cambios que se aplicarán a los documentos coincidentes.

Mientras ejecutan operaciones de actualización, las funciones de Atlas agregan temporalmente un campo reservado, _id__baas_transaction, a los documentos. Una vez que un documento se actualiza con éxito, las funciones de Atlas remueven este campo.

Si deseas utilizar otra herramienta para modificar los datos de una colección, asegúrate de que elimine este campo antes de realizar cambios.

Por ejemplo, si se utiliza la shell de mongosh para actualizar documentos en la colección de productos, el comando podría parecerse al siguiente código:

db.products.update(
{ sku: "unknown" },
{ $unset: { _id__baas_transaction: "" } }
)

Puede actualizar un solo documento utilizando el método collection.updateOne().

El siguiente snippet de Función actualiza la name de un solo documento en la colección items de lego a blocks , y añade un price de 20.99:

const query = { "name": "lego" };
const update = {
"$set": {
"name": "blocks",
"price": 20.99,
"category": "toys"
}
};
const options = { "upsert": false };
itemsCollection.updateOne(query, update, options)
.then(result => {
const { matchedCount, modifiedCount } = result;
if(matchedCount && modifiedCount) {
console.log(`Successfully updated the item.`)
}
})
.catch(err => console.error(`Failed to update the item: ${err}`))

Alternativamente, puedes actualizar un solo documento usando collection.findOneAndUpdate() o collection.findOneAndReplace(). Ambos métodos le permiten encontrar, modificar y devolver el documento actualizado en una sola operación.

Puedes actualizar varios documentos en una colección utilizando el método collection.updateMany().

El siguiente Function snippet actualiza todos los documentos de la colección items multiplicando sus valores quantity por 10:

const query = {};
const update = { "$mul": { "quantity": 10 } };
const options = { "upsert": false }
return itemsCollection.updateMany(query, update, options)
.then(result => {
const { matchedCount, modifiedCount } = result;
console.log(`Successfully matched ${matchedCount} and modified ${modifiedCount} items.`)
return result
})
.catch(err => console.error(`Failed to update items: ${err}`))

Si una operación de actualización no coincide con ningún documento en la colección, puedes insertar automáticamente un nuevo documento en la colección que coincida con la query de actualización configurando la opción upsert en true.

El siguiente Function snippet actualiza un documento en la colección items que tiene un name de board game, incrementando su quantity en 5. La opción upsert está habilitada, por lo que si ningún documento tiene un valor name de "board game", MongoDB inserta un nuevo documento con el campo name establecido en "board game" y el valor quantity establecido en 5:

const query = { "name": "board games" };
const update = { "$inc": { "quantity": 5 } };
const options = { "upsert": true };
itemsCollection.updateOne(query, update, options)
.then(result => {
const { matchedCount, modifiedCount, upsertedId } = result;
if(upsertedId) {
console.log(`Document not found. Inserted a new document with _id: ${upsertedId}`)
} else {
console.log(`Successfully increased ${query.name} quantity by ${update.$inc.quantity}`)
}
})
.catch(err => console.error(`Failed to upsert document: ${err}`))

Los operadores de campos te permiten modificar los campos y valores de un documento.

Se puede usar el operador $set para asignar el valor de un único campo sin afectar a otros campos en un documento.

{ "$set": { "<Field Name>": <Value>, ... } }

Puedes usar el operador $rename para cambiar el nombre de un solo campo en un documento.

{ "$rename": { "<Current Field Name>": <New Field Name>, ... } }

Puedes usar el operador $inc para añadir una cantidad específica al valor actual de un campo. El número puede ser positivo o negativo.

{ "$inc": { "<Field Name>": <Increment Number>, ... } }

Puedes usar el operador $mul para multiplicar un número especificado con el valor actual de un campo. El número puede ser positivo o negativo.

{ "$mul": { "<Field Name>": <Multiple Number>, ... } }

Los operadores de arreglo le permiten trabajar con valores dentro de los arreglos.

Puedes usar el operador $push para agregar un valor al final de un campo de arreglo.

{ "$push": { "<Array Field Name>": <New Array Element>, ... } }

Puedes utilizar el operador $pop para remover el primer o el último elemento de un campo de arreglo. Especifique -1 para remover el primer elemento y 1 para remover el último elemento.

{ "$pop": { "<Array Field Name>": <-1 | 1>, ... } }

Puedes utilizar el operador $addToSet para añadir un valor a un campo de arreglo si ese valor aún no está incluido en el arreglo. Si el valor ya está presente, $addToSet no hace nada.

{ "$addToSet": { "<Array Field Name>": <Potentially Unique Value>, ... } }

Puede usar el operador $pull para remover todas las instancias de cualquier valor que coincida con una condición especificada de un campo de arreglo.

{ "$pull": { "<Array Field Name>": <Value | Expression>, ... } }

Puedes usar el $[] (Actualización Posicional Total) operador para actualizar todos los elementos en un campo de arreglo:

Ejemplo

Considera una colección de students que describa a los estudiantes individuales de una clase. Los documentos incluyen cada uno un campo grades que contiene un arreglo de números:

{ "_id" : 1, "grades" : [ 85, 82, 80 ] }
{ "_id" : 2, "grades" : [ 88, 90, 92 ] }
{ "_id" : 3, "grades" : [ 85, 100, 90 ] }

La siguiente operación de actualización suma 10 a todos los valores en el arreglo grades de cada estudiante:

await students.updateMany(
{},
{ $inc: { "grades.$[]": 10 } },
)

Después de la actualización, cada valor de calificación ha aumentado en 10:

{ "_id" : 1, "grades" : [ 95, 92, 90 ] }
{ "_id" : 2, "grades" : [ 98, 100, 102 ] }
{ "_id" : 3, "grades" : [ 95, 110, 100 ] }

Puedes usar el operador $[element] (actualización posicional filtrada) para actualizar elementos específicos en un campo de arreglo basado en un filtro de arreglo:

Ejemplo

Considere una colección students que describe a los estudiantes de una clase. Cada documento incluye un campo grades que contiene una matriz de números, algunos de los cuales son mayores que 100:

{ "_id" : 1, "grades" : [ 15, 92, 90 ] }
{ "_id" : 2, "grades" : [ 18, 100, 102 ] }
{ "_id" : 3, "grades" : [ 15, 110, 100 ] }

La siguiente operación de actualización establece todos los valores de calificación superiores a 100 exactamente en 100:

await students.updateMany(
{ },
{
$set: {
"grades.$[grade]" : 100
}
},
{
arrayFilters: [{ "grade": { $gt: 100 } }]
}
)

Después de la actualización, todos los valores de calificaciones mayores a 100 se establecen exactamente en 100 y el resto se mantienen igual:

{ "_id" : 1, "grades" : [ 15, 92, 90 ] }
{ "_id" : 2, "grades" : [ 18, 100, 100 ] }
{ "_id" : 3, "grades" : [ 15, 100, 100 ] }

Las operaciones de borrado buscan documentos existentes en una colección de MongoDB y los remueven. Utilizas la sintaxis estándar de query de MongoDB para especificar los documentos que deseas borrar.

Puedes borrar un solo documento de una colección utilizando el método collection.deleteOne().

El siguiente snippet de función elimina un documento en la colección items que tiene un valor de name de lego:

const query = { "name": "lego" };
itemsCollection.deleteOne(query)
.then(result => console.log(`Deleted ${result.deletedCount} item.`))
.catch(err => console.error(`Delete failed with error: ${err}`))

O, de forma alternativa, puedes actualizar un único documento utilizando collection.findOneAndDelete(). Este método te permite localizar, remover y recuperar el documento borrado en una sola operación.

Puedes borrar varios elementos de una colección usando el método collection.deleteMany().

El siguiente snippet borra todos los documentos de la colección items que no tienen ningún reviews:

const query = { "reviews": { "$size": 0 } };
itemsCollection.deleteMany(query)
.then(result => console.log(`Deleted ${result.deletedCount} item(s).`))
.catch(err => console.error(`Delete failed with error: ${err}`))

Una operación masiva combina varias operaciones de guardado en una sola operación. Puedes emitir un comando de guardado masivo usando el método collection.bulkWrite().

exports = async function(arg){
const doc1 = { "name": "velvet elvis", "quantity": 20, "reviews": [] };
const doc2 = { "name": "mock turtleneck", "quantity": 30, "reviews": [] };
var collection = context.services.get("mongodb-atlas")
.db("store")
.collection("purchases");
return await collection.bulkWrite(
[{ insertOne: doc1}, { insertOne: doc2}],
{ordered:true});
};

MongoDB admite transacciones multidocumento que permiten leer y guardar varios documentos atómicamente, incluso entre colecciones.

Para realizar una transacción:

  1. Obtenga y comience una sesión de cliente con client.startSession().

  2. Llama a session.withTransaction() para definir la transacción. El método toma una función de retorno asíncrona y, opcionalmente, un objeto de configuración que define configuración de lectura y guardado personalizada para la transacción.

    session.withTransaction(async () => {
    // ... Run MongoDB operations in this callback
    }, {
    readPreference: "primary",
    readConcern: { level: "local" },
    writeConcern: { w: "majority" },
    })
  3. En la función de retorno de la transacción, ejecuta las queries de MongoDB que deseas incluir en la transacción. Asegúrese de pasar el session a cada query para asegurarse de que esté incluido en la transacción.

    await accounts.updateOne(
    { name: userSubtractPoints },
    { $inc: { browniePoints: -1 * pointVolume } },
    { session }
    );
  4. Si la función de retorno encuentra un error, llama a session.abortTransaction() para detener la transacción. Una transacción abortada no modifica ningún dato.

    try {
    // ...
    } catch (err) {
    await session.abortTransaction();
    }
  5. Cuando la transacción esté completa, llama a session.endSession() para finalizar la sesión y liberar recursos.

    try {
    // ...
    } finally {
    await session.endSession();
    }

El siguiente ejemplo crea dos usuarios, "henry" y "michelle", y utiliza una transacción para transferir "browniePoints" entre esos usuarios atómicamente:

exports = function () {
const client = context.services.get("mongodb-atlas");
db = client.db("exampleDatabase");
accounts = db.collection("accounts");
browniePointsTrades = db.collection("browniePointsTrades");
// create user accounts with initial balances
accounts.insertOne({ name: "henry", browniePoints: 42 });
accounts.insertOne({ name: "michelle", browniePoints: 144 });
// trade points between user accounts in a transaction
tradeBrowniePoints(
client,
accounts,
browniePointsTrades,
"michelle",
"henry",
5
);
return "Successfully traded brownie points.";
};
async function tradeBrowniePoints(
client,
accounts,
browniePointsTrades,
userAddPoints,
userSubtractPoints,
pointVolume
) {
// Step 1: Start a Client Session
const session = client.startSession();
// Step 2: Optional. Define options to use for the transaction
const transactionOptions = {
readPreference: "primary",
readConcern: { level: "local" },
writeConcern: { w: "majority" },
};
// Step 3: Use withTransaction to start a transaction, execute the callback, and commit (or abort on error)
// Note: The callback for withTransaction MUST be async and/or return a Promise.
try {
await session.withTransaction(async () => {
// Step 4: Execute the queries you would like to include in one atomic transaction
// Important:: You must pass the session to the operations
await accounts.updateOne(
{ name: userSubtractPoints },
{ $inc: { browniePoints: -1 * pointVolume } },
{ session }
);
await accounts.updateOne(
{ name: userAddPoints },
{ $inc: { browniePoints: pointVolume } },
{ session }
);
await browniePointsTrades.insertOne(
{
userAddPoints: userAddPoints,
userSubtractPoints: userSubtractPoints,
pointVolume: pointVolume,
},
{ session }
);
}, transactionOptions);
} catch (err) {
// Step 5: Handle errors with a transaction abort
await session.abortTransaction();
} finally {
// Step 6: End the session when you complete the transaction
await session.endSession();
}
}