Join us at MongoDB.local London on 7 May to unlock new possibilities for your data. Use WEB50 to save 50%.
Register now >
Docs Menu
Docs Home
/ /
Atlas App Services

Query MongoDB - Java SDK

Puede consultar datos almacenados en MongoDB Atlas directamente desde el código de su aplicación Android utilizando MongoClient del SDK Java de Realm con el API de consulta. Atlas App Services proporciona reglas de acceso a datos en colecciones para recuperar resultados de forma segura según el usuario conectado o el contenido de cada documento.

Las siguientes acciones permiten el acceso a un clúster MongoDB Atlas vinculado desde una aplicación de Android mediante el SDK de Realm.

Nota

Cada operación descrita en esta página utiliza una consulta para buscar coincidencias en determinados documentos de la colección en la que se ejecuta la operación. Cuando un filtro busca coincidencias en varios documentos de una colección, estos se devuelven en un orden indeterminado a menos que se especifique un parámetro de ordenación. Esto significa que si no se especifica una ordenación para los... findOne(), o, updateOne() deleteOne() su operación podría coincidir con cualquier documento que coincida con la consulta. Para más información sobre la ordenación, consulte cursor.sort().

Existen variedad de razones por las que podría querer query una fuente de datos de MongoDB. Trabajar con datos en tu cliente a través de Atlas Device Sync no siempre es práctico o posible. Podrías querer query MongoDB cuando:

  • The data set is large or the client device has constraints against loading the entire data set

  • You are creating or updating custom user data

  • Estás recuperando documentos que no están modelados en Realm

  • Your app needs to access collections that don't have strict schemas

  • A non-Realm service generates collections that you want to access

While not exhaustive, these are some common use cases for querying MongoDB directly.

Antes de poder consultar MongoDB desde su aplicación Android, debe configurar el acceso a datos de MongoDB en su aplicación de App Services. Para saber cómo configurar su aplicación backend para que el SDK de Realm pueda consultar Atlas, consulte "Configurar el acceso a datos de MongoDB" en la documentación de App Services.

1

Siga los pasos en la guía Install the Realm Java SDK.

2

Follow the steps in the Link a MongoDB data source guide. Assign your service a meaningful name -- you'll need it to connect to the cluster using the Realm SDK.

3

For CRUD operations on a remote MongoDB collection, you will use one or more of the following import statements:

// Base Realm Packages
import io.realm.mongodb.App;
import io.realm.mongodb.AppConfiguration;
// Realm Authentication Packages
import io.realm.mongodb.User;
import io.realm.mongodb.Credentials;
// MongoDB Service Packages
import io.realm.mongodb.mongo.MongoClient;
import io.realm.mongodb.mongo.MongoDatabase;
import io.realm.mongodb.mongo.MongoCollection;
// Utility Packages
import org.bson.Document;
// Base Realm Packages
import io.realm.mongodb.App
import io.realm.mongodb.AppConfiguration
// Realm Authentication Packages
import io.realm.mongodb.User
import io.realm.mongodb.Credentials
// MongoDB Service Packages
import io.realm.mongodb.mongo.MongoClient
import io.realm.mongodb.mongo.MongoDatabase
import io.realm.mongodb.mongo.MongoCollection
// Utility Packages
import org.bson.Document
4

Para conectarte a una instancia de MongoDB, necesitarás un usuario con acceso a una colección de MongoDB. Inicie sesión en su aplicación como ese usuario y luego utilice el siguiente código para instanciar un identificador de colección local de MongoDB.

User user = app.currentUser();
MongoClient mongoClient =
user.getMongoClient("mongodb-atlas");
MongoDatabase mongoDatabase =
mongoClient.getDatabase("plant-data-database");
// registry to handle POJOs (Plain Old Java Objects)
CodecRegistry pojoCodecRegistry = fromRegistries(AppConfiguration.DEFAULT_BSON_CODEC_REGISTRY,
fromProviders(PojoCodecProvider.builder().automatic(true).build()));
MongoCollection<Plant> mongoCollection =
mongoDatabase.getCollection(
"plant-data-collection",
Plant.class).withCodecRegistry(pojoCodecRegistry);
Log.v("EXAMPLE", "Successfully instantiated the MongoDB collection handle");
val user = app.currentUser()
val mongoClient =
user!!.getMongoClient("mongodb-atlas")
val mongoDatabase =
mongoClient.getDatabase("plant-data-database")
// registry to handle POJOs (Plain Old Java Objects)
val pojoCodecRegistry = CodecRegistries.fromRegistries(
AppConfiguration.DEFAULT_BSON_CODEC_REGISTRY,
CodecRegistries.fromProviders(
PojoCodecProvider.builder().automatic(true).build()))
val mongoCollection =
mongoDatabase.getCollection(
"plant-data-collection",
Plant::class.java).withCodecRegistry(pojoCodecRegistry)
Log.v("EXAMPLE", "Successfully instantiated the MongoDB collection handle")

Nota

Using Custom Classes with MongoDB

To use classes other than the built-in Document class with MongoDB, you can add codecs to your MongoCollection instances. In the above example, we add the PojoCodecProvider to support Plain Old Java Objects (POJOs). Custom object support requires two codec providers:

  • el proveedor de códec predeterminado, que proporciona soporte para tipos Java integrados (a los que se accede a través de AppConfiguration.DEFAULT_BSON_CODEC_REGISTRY)

  • PojoCodecProvider, que crea automáticamente nuevos códecs para soporte clases POJO.

El SDK revisa los registros en orden hasta que uno devuelve un códec para la clase solicitada. Por lo tanto, debe listar primero el registro de códec predeterminado y PojoCodecProvider siempre debe ser el último CodecProvider, ya que puede proporcionar un códec para casi cualquier clase.

Los siguientes ejemplos operan en una colección de MongoDB que describe el inventario en una cadena de tiendas de plantas. Considera la siguiente colección de documentos que describen varios tipos de plantas en venta en un almacenar:

Plant.java
import org.bson.codecs.pojo.annotations.BsonProperty;
import org.bson.types.ObjectId;
public class Plant {
private ObjectId id;
private String name;
private String sunlight;
private String color;
private String type;
@BsonProperty("_partition")
private String partition;
// empty constructor required for MongoDB Data Access POJO codec compatibility
public Plant() {}
public Plant(ObjectId id, String name, String sunlight, String color, String type, String partition) {
this.id = id;
this.name = name;
this.sunlight = sunlight;
this.color = color;
this.type = type;
this.partition = partition;
}
public ObjectId getId() { return id; }
public void setId(ObjectId id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getSunlight() { return sunlight; }
public void setSunlight(String sunlight) { this.sunlight = sunlight; }
public String getColor() { return color; }
public void setColor(String color) { this.color = color; }
public String getType() { return type; }
public void setType(String type) { this.type = type; }
public String getPartition() { return partition; }
public void setPartition(String partition) { this.partition = partition; }
@Override
public String toString() {
return "Plant [id=" + id + ", name=" + name + ", sunlight=" + sunlight + ", color=" + color + ", type=" + type + ", partition=" + partition + "]";
}
}
User user = app.currentUser();
MongoClient mongoClient =
user.getMongoClient("mongodb-atlas");
MongoDatabase mongoDatabase =
mongoClient.getDatabase("plant-data-database");
// registry to handle POJOs (Plain Old Java Objects)
CodecRegistry pojoCodecRegistry = fromRegistries(AppConfiguration.DEFAULT_BSON_CODEC_REGISTRY,
fromProviders(PojoCodecProvider.builder().automatic(true).build()));
MongoCollection<Plant> mongoCollection =
mongoDatabase.getCollection(
"plant-data-collection",
Plant.class).withCodecRegistry(pojoCodecRegistry);
mongoCollection.insertMany(Arrays.asList(
new Plant(new ObjectId(),
"venus flytrap",
"full",
"white",
"perennial",
"Store 42"),
new Plant(new ObjectId(),
"sweet basil",
"partial",
"green",
"annual",
"Store 42"),
new Plant(new ObjectId(),
"thai basil",
"partial",
"green",
"perennial",
"Store 42"),
new Plant(new ObjectId(),
"helianthus",
"full",
"yellow",
"annual",
"Store 42"),
new Plant(new ObjectId(),
"petunia",
"full",
"purple",
"annual",
"Store 47")));
Log.v("EXAMPLE", "Successfully inserted the sample data.");
Plant.kt
import org.bson.codecs.pojo.annotations.BsonProperty
import org.bson.types.ObjectId
open class Plant(val id : ObjectId = ObjectId(),
var name : String? = null,
var sunlight : String? = null,
var color : String? = null,
var type : String? = null,
@field:BsonProperty("_partition") // specify that this is a field-level annotation
var partition : String? = null) {
override fun toString(): String {
return "Plant [id=$id, name=$name, sunlight=$sunlight, color=$color, type=$type, partition=$partition]"
}
}
val user = app.currentUser()
val mongoClient =
user!!.getMongoClient("mongodb-atlas")
val mongoDatabase =
mongoClient.getDatabase("plant-data-database")
// registry to handle POJOs (Plain Old Java Objects)
val pojoCodecRegistry = CodecRegistries.fromRegistries(
AppConfiguration.DEFAULT_BSON_CODEC_REGISTRY,
CodecRegistries.fromProviders(
PojoCodecProvider.builder().automatic(true).build()))
val mongoCollection =
mongoDatabase.getCollection(
"plant-data-collection",
Plant::class.java).withCodecRegistry(pojoCodecRegistry)
mongoCollection.insertMany(
listOf(
Plant(
ObjectId(),
"venus flytrap",
"full",
"white",
"perennial",
"Store 42"
),
Plant(
ObjectId(),
"sweet basil",
"partial",
"green",
"annual",
"Store 42"
),
Plant(
ObjectId(),
"thai basil",
"partial",
"green",
"perennial",
"Store 42"
),
Plant(
ObjectId(),
"helianthus",
"full",
"yellow",
"annual",
"Store 42"
),
Plant(
ObjectId(),
"petunia",
"full",
"purple",
"annual",
"Store 47"
)
)
)
Log.v("EXAMPLE", "Successfully Successfully inserted the sample data.")

These code snippets demonstrate how to insert one or more documents into a MongoDB collection from a mobile application. Insert operations take a document or documents to add to MongoDB as an argument and return a RealmResultTask that resolves to an object that contains the results of the execution of the operation.

Puedes insertar un solo documento utilizando colección.insertOne().

The following snippet inserts a single document describing a "lily of the valley" plant into a collection of documents that describe plants for sale in a group of stores:

Plant plant = new Plant(
new ObjectId(),
"lily of the valley",
"full",
"white",
"perennial",
"Store 47");
mongoCollection.insertOne(plant).getAsync(task -> {
if (task.isSuccess()) {
Log.v("EXAMPLE", "successfully inserted a document with id: " + task.get().getInsertedId());
} else {
Log.e("EXAMPLE", "failed to insert documents with: " + task.getError().getErrorMessage());
}
});
val plant = Plant(
ObjectId(),
"lily of the valley",
"full",
"white",
"perennial",
"Store 47"
)
mongoCollection?.insertOne(plant)?.getAsync { task ->
if (task.isSuccess) {
Log.v(
"EXAMPLE",
"successfully inserted a document with id: ${task.get().insertedId}"
)
} else {
Log.e("EXAMPLE", "failed to insert documents with: ${task.error}")
}
}

Running this snippet produces output resembling the following:

V/EXAMPLE: successfully inserted a document with id: BsonObjectId{value=5f19...}

Puede insertar varios documentos al mismo tiempo utilizando collection.insertMany().

El siguiente fragmento inserta tres documentos que describen plantas en una colección de documentos que describen plantas en venta en un grupo de tiendas:

List<Plant> plants = Arrays.asList(
new Plant(new ObjectId(),
"rhubarb",
"full",
"red",
"perennial",
"Store 47"),
new Plant(new ObjectId(),
"wisteria lilac",
"partial",
"purple",
"perennial",
"Store 42"),
new Plant(new ObjectId(),
"daffodil",
"full",
"yellow",
"perennial",
"Store 42"));
mongoCollection.insertMany(plants).getAsync(task -> {
if (task.isSuccess()) {
int insertedCount = task.get().getInsertedIds().size();
Log.v("EXAMPLE", "successfully inserted " + insertedCount + " documents into the collection.");
} else {
Log.e("EXAMPLE", "failed to insert documents with: ", task.getError());
}
});
val plants = listOf(
Plant(
ObjectId(),
"rhubarb",
"full",
"red",
"perennial",
"Store 47"
),
Plant(
ObjectId(),
"wisteria lilac",
"partial",
"purple",
"perennial",
"Store 42"
),
Plant(
ObjectId(),
"daffodil",
"full",
"yellow",
"perennial",
"Store 42"
)
)
mongoCollection.insertMany(plants).getAsync { task ->
if (task.isSuccess) {
val insertedCount = task.get().insertedIds.size
Log.v(
"EXAMPLE",
"successfully inserted $insertedCount documents into the collection."
)
} else {
Log.e("EXAMPLE", "failed to insert documents with: ${task.error}")
}
}

Running this snippet produces output resembling the following:

V/EXAMPLE: successfully inserted 3 documents into the collection.

Estos fragmentos de código muestran cómo leer datos almacenados en una colección de MongoDB desde una aplicación móvil. Las operaciones de lectura utilizan consultas para especificar qué documentos devolver de la base de datos. Las operaciones de lectura devuelven una tarea.que se resuelve en un solo documento coincidente (en el caso findOne() de), un long valor numérico (en el caso count() de) o un iterador que le permite recorrer la colección de documentos coincidentes (en el caso find() de).

Puede encontrar un solo documento utilizando collection.findOne().

El siguiente fragmento encuentra un solo documento de una colección de documentos que describen plantas a la venta en un grupo de tiendas donde el campo del documento de planta type contiene el valor de cadena "perenne":

Document queryFilter = new Document("type", "perennial");
mongoCollection.findOne(queryFilter).getAsync(task -> {
if (task.isSuccess()) {
Plant result = task.get();
Log.v("EXAMPLE", "successfully found a document: " + result);
} else {
Log.e("EXAMPLE", "failed to find document with: ", task.getError());
}
});
val queryFilter = Document("type", "perennial")
mongoCollection.findOne(queryFilter)
.getAsync { task ->
if (task.isSuccess) {
val result = task.get()
Log.v("EXAMPLE", "successfully found a document: $result")
} else {
Log.e("EXAMPLE", "failed to find document with: ${task.error}")
}
}

La ejecución de este fragmento produce un resultado similar al siguiente:

V/EXAMPLE: successfully found a document: Plant [id=5f18..., name=venus flytrap, sunlight=full, color=white, type=perennial, partition=Store 42]

You can find multiple documents using collection.find().

El siguiente fragmento busca todos los documentos en una colección de documentos que describen plantas en venta en un grupo de tiendas que contienen un campo llamado _partition con un valor de "Tienda 42":

Document queryFilter = new Document("_partition", "Store 42");
RealmResultTask<MongoCursor<Plant>> findTask = mongoCollection.find(queryFilter).iterator();
findTask.getAsync(task -> {
if (task.isSuccess()) {
MongoCursor<Plant> results = task.get();
Log.v("EXAMPLE", "successfully found all plants for Store 42:");
while (results.hasNext()) {
Log.v("EXAMPLE", results.next().toString());
}
} else {
Log.e("EXAMPLE", "failed to find documents with: ", task.getError());
}
});
val queryFilter = Document("_partition", "Store 42")
val findTask = mongoCollection.find(queryFilter).iterator()
findTask.getAsync { task ->
if (task.isSuccess) {
val results = task.get()
Log.v("EXAMPLE", "successfully found all plants for Store 42:")
while (results.hasNext()) {
Log.v("EXAMPLE", results.next().toString())
}
} else {
Log.e("EXAMPLE", "failed to find documents with: ${task.error}")
}
}

Running this snippet produces output resembling the following:

V/EXAMPLE: successfully found all plants for Store 42:
V/EXAMPLE: Plant [id=5f18..., name=venus flytrap, sunlight=full, color=white, type=perennial, partition=Store 42]
V/EXAMPLE: Plant [id=5f18..., name=sweet basil, sunlight=partial, color=green, type=annual, partition=Store 42]
V/EXAMPLE: Plant [id=5f18..., name=thai basil, sunlight=partial, color=green, type=perennial, partition=Store 42]
V/EXAMPLE: Plant [id=5f18..., name=helianthus, sunlight=full, color=yellow, type=annual, partition=Store 42]

Puedes contar los documentos de una colección usando collection.count(). Puedes especificar una consulta opcional para determinar qué documentos contar. Si no especificas una consulta, la acción cuenta todos los documentos de la colección.

El siguiente fragmento cuenta la cantidad de documentos en una colección de documentos que describen plantas en venta en un grupo de tiendas:

mongoCollection.count().getAsync(task -> {
if (task.isSuccess()) {
long count = task.get();
Log.v("EXAMPLE",
"successfully counted, number of documents in the collection: " +
count);
} else {
Log.e("EXAMPLE", "failed to count documents with: ", task.getError());
}
});
mongoCollection.count().getAsync { task ->
if (task.isSuccess) {
val count = task.get()
Log.v("EXAMPLE", "successfully counted, number of documents in the collection: $count")
} else {
Log.e("EXAMPLE", "failed to count documents with: ${task.error}")
}
}

Running this snippet produces output resembling the following:

V/EXAMPLE: successfully counted, number of documents in the collection: 5

These code snippets demonstrate how to update data stored in a MongoDB collection from a mobile application. Update operations use queries to specify which documents to update and update operators to describe how to mutate documents that match the query. Update operations return a Task that resolves to an object that contains the results of the execution of the operation.

You can update a single document using collection.updateOne().

The following snippet updates a single document in a collection of documents that describe plants for sale in a group of stores. This operation queries for a document where the name field contains the value "petunia" and changes the value of the first matched document's sunlight field to "partial":

Document queryFilter = new Document("name", "petunia");
Document updateDocument = new Document("$set", new Document("sunlight", "partial"));
mongoCollection.updateOne(queryFilter, updateDocument).getAsync(task -> {
if (task.isSuccess()) {
long count = task.get().getModifiedCount();
if (count == 1) {
Log.v("EXAMPLE", "successfully updated a document.");
} else {
Log.v("EXAMPLE", "did not update a document.");
}
} else {
Log.e("EXAMPLE", "failed to update document with: ", task.getError());
}
});
val queryFilter = Document("name", "petunia")
val updateDocument = Document("\$set", Document("sunlight", "partial"))
mongoCollection.updateOne(queryFilter, updateDocument).getAsync { task ->
if (task.isSuccess) {
val count = task.get().modifiedCount
if (count == 1L) {
Log.v("EXAMPLE", "successfully updated a document.")
} else {
Log.v("EXAMPLE", "did not update a document.")
}
} else {
Log.e("EXAMPLE", "failed to update document with: ${task.error}")
}
}

Running this snippet produces output resembling the following:

V/EXAMPLE: successfully updated a document.

Puede actualizar varios documentos utilizando collection.updateMany().

El siguiente fragmento actualiza varios documentos de una colección que describen plantas en venta en un grupo de tiendas. Esta operación busca documentos cuyo _partition campo contenga el valor "Tienda 47" y cambia el valor del _partition campo de cada documento coincidente a "Tienda 51":

Document queryFilter = new Document("_partition", "Store 47");
Document updateDocument = new Document("$set", new Document("_partition", "Store 51"));
mongoCollection.updateMany(queryFilter, updateDocument).getAsync(task -> {
if (task.isSuccess()) {
long count = task.get().getModifiedCount();
if (count != 0) {
Log.v("EXAMPLE", "successfully updated " + count + " documents.");
} else {
Log.v("EXAMPLE", "did not update any documents.");
}
} else {
Log.e("EXAMPLE", "failed to update documents with: ", task.getError());
}
});
val queryFilter = Document("_partition", "Store 47")
val updateDocument = Document("\$set", Document("_partition", "Store 51"))
mongoCollection.updateMany(queryFilter, updateDocument).getAsync { task ->
if (task.isSuccess) {
val count = task.get().modifiedCount
if (count != 0L) {
Log.v("EXAMPLE", "successfully updated $count documents.")
} else {
Log.v("EXAMPLE", "did not update any documents.")
}
} else {
Log.e("EXAMPLE", "failed to update documents with: ${task.error}")
}
}

Running this snippet produces output resembling the following:

V/EXAMPLE: successfully updated 2 documents.

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 fragmento actualiza un documento de una colección que describe plantas en venta en un grupo de tiendas o inserta un nuevo documento si ningún documento coincide con la consulta. Esta operación busca documentos donde:

  • el campo sunlight tiene un valor de "completo"

  • El campo type tiene un valor de "perenne"

  • the color field has a value of "green"

  • el campo _partition tiene el valor "Store 47".

Because this snippet sets the upsert option to true, if no document matches the query, MongoDB creates a new document that includes both the query and specified updates:

Document queryFilter = new Document("sunlight", "full")
.append("type", "perennial")
.append("color", "green")
.append("_partition", "Store 47");
Document updateDocument = new Document("$set", new Document("name", "sweet basil"));
UpdateOptions updateOptions = new UpdateOptions().upsert(true);
mongoCollection.updateOne(queryFilter, updateDocument, updateOptions).getAsync(task -> {
if (task.isSuccess()) {
if(task.get().getUpsertedId() != null) {
Log.v("EXAMPLE", "successfully upserted a document with id " +
task.get().getUpsertedId());
} else {
Log.v("EXAMPLE", "successfully updated a document.");
}
} else {
Log.e("EXAMPLE", "failed to update or insert document with: ",
task.getError());
}
});
val queryFilter = Document("sunlight", "full")
.append("type", "perennial")
.append("color", "green")
.append("_partition", "Store 47")
val updateDocument = Document("\$set", Document("name", "sweet basil"))
val updateOptions = UpdateOptions().upsert(true)
mongoCollection.updateOne(queryFilter, updateDocument, updateOptions)
.getAsync { task ->
if (task.isSuccess) {
if (task.get().upsertedId != null) {
Log.v("EXAMPLE", "successfully upserted a document with id ${task.get().upsertedId}")
} else {
Log.v("EXAMPLE", "successfully updated a document.")
}
} else {
Log.e("EXAMPLE", "failed to update or insert document with: ${task.error}")
}
}

Running this snippet produces output resembling the following:

V/EXAMPLE: successfully upserted a document with id: BsonObjectId{value=5f19...}

These code snippets demonstrate how to delete documents that are stored in a MongoDB collection from a mobile application. Delete operations use a query to specify which documents to delete and return a Task that resolves to an object that contains the results of the execution of the operation.

Puedes eliminar un solo documento de una colección utilizando collection.deleteOne().

The following snippet deletes one document in a collection of documents that describe plants for sale in a group of stores. This operation queries for a document where the color field has a value of "green" and deletes the first document that matches the query:

Document queryFilter = new Document("color", "green");
mongoCollection.deleteOne(queryFilter).getAsync(task -> {
if (task.isSuccess()) {
long count = task.get().getDeletedCount();
if (count == 1) {
Log.v("EXAMPLE", "successfully deleted a document.");
} else {
Log.v("EXAMPLE", "did not delete a document.");
}
} else {
Log.e("EXAMPLE", "failed to delete document with: ", task.getError());
}
});
val queryFilter = Document("color", "green")
mongoCollection.deleteOne(queryFilter).getAsync { task ->
if (task.isSuccess) {
val count = task.get().deletedCount
if (count == 1L) {
Log.v("EXAMPLE", "successfully deleted a document.")
} else {
Log.v("EXAMPLE", "did not delete a document.")
}
} else {
Log.e("EXAMPLE", "failed to delete document with: ${task.error}")
}
}

Running this snippet produces output resembling the following:

V/EXAMPLE: successfully deleted a document.

Puede borrar varios elementos de una colección usando collection.deleteMany().

El siguiente snippet borra todos los documentos en una colección de documentos que describe plantas en venta en un grupo de tiendas que compara con la query que coincide con documentos que contienen tanto un valor de campo sunlight de "full" como un valor de campo type de "annual".

Document queryFilter = new Document("sunlight", "full")
.append("type", "annual");
mongoCollection.deleteMany(queryFilter).getAsync(task -> {
if (task.isSuccess()) {
long count = task.get().getDeletedCount();
if (count != 0) {
Log.v("EXAMPLE", "successfully deleted " + count + " documents.");
} else {
Log.v("EXAMPLE", "did not delete any documents.");
}
} else {
Log.e("EXAMPLE", "failed to delete documents with: ", task.getError());
}
});
val queryFilter = Document("sunlight", "full").append("type", "annual")
mongoCollection.deleteMany(queryFilter).getAsync { task ->
if (task.isSuccess) {
val count = task.get().deletedCount
if (count != 0L) {
Log.v("EXAMPLE", "successfully deleted $count documents.")
} else {
Log.v("EXAMPLE", "did not delete any documents.")
}
} else {
Log.e("EXAMPLE", "failed to delete documents with: ${task.error}")
}
}

Running this snippet produces output resembling the following:

V/EXAMPLE: succcessfully deleted 2 documents.

Estos fragmentos de código demuestran cómo configurar y ejecutar operaciones de vigilancia en una colección.

Importante

Serverless Limitations

No puedes observar cambios si la fuente de datos es una instancia sin servidor de Atlas. El servidor sin servidor de MongoDB actualmente no admite flujos de cambios, que se emplean en las colecciones monitoreadas para escuchar cambios.

You can open a stream of changes made to a collection by calling collection.watch() or collection.watchAsync(). You can watch for changes to specific documents in a collection by passing the object ids of the objects you would like to monitor as a variable number of arguments.

The following snippet watches for changes to any documents in the plants collection:

RealmEventStreamAsyncTask<Plant> watcher = mongoCollection.watchAsync();
watcher.get(result -> {
if (result.isSuccess()) {
Log.v("EXAMPLE", "Event type: " +
result.get().getOperationType() + " full document: " +
result.get().getFullDocument());
} else {
Log.e("EXAMPLE", "failed to subscribe to changes in the collection with : ",
result.getError());
}
});
Plant triffid = new Plant(
new ObjectId(),
"triffid",
"low",
"green",
"perennial",
"Store 47");
mongoCollection.insertOne(triffid).getAsync(task -> {
if (task.isSuccess()) {
BsonObjectId insertedId = task.get().getInsertedId().asObjectId();
Log.v("EXAMPLE", "successfully inserted a document with id " + insertedId);
} else {
Log.e("EXAMPLE", "failed to insert document with: ", task.getError());
}
});
val watcher = mongoCollection.watchAsync()
watcher[{ result ->
if (result.isSuccess) {
Log.v("EXAMPLE", "Event type: ${result.get().operationType} full document: ${result.get().fullDocument}")
} else {
Log.e("EXAMPLE", "failed to subscribe to changes in the collection with : ${result.error}")
}
}]
val triffid =
Plant(
ObjectId(),
"triffid",
"low",
"green",
"perennial",
"Store 47"
)
mongoCollection.insertOne(triffid).getAsync { task ->
if (task.isSuccess) {
val insertedId = task.get().insertedId.asObjectId()
Log.v("EXAMPLE", "successfully inserted a document with id $insertedId")
} else {
Log.e("EXAMPLE", "failed to insert document with: ${task.error}")
}
}

Running this snippet produces output resembling the following:

V/EXAMPLE: successfully inserted a document with id BsonObjectId{value=5f6bb...}
V/EXAMPLE: Event type: INSERT full document: Plant [id=5f6bb..., name=triffid, sunlight=low, color=green, type=perennial, partition=Store 47]

Puedes abrir un flujo de cambios realizados en documentos de una colección que cumplan ciertos criterios llamando a collection.watchWithFilter() o collection.watchWithFilterAsync(). Ambos métodos aceptan un parámetro Document o BsonDocument que se utiliza como la query de un operador $match para procesar cada evento de base de datos que ocurre mientras se supervisa la colección.

The following snippet watches for changes to documents in the plants collection, but only triggers the provided callback for events corresponding to documents belonging to the partition named "Store 42":

RealmEventStreamAsyncTask<Plant> watcher = mongoCollection
.watchWithFilterAsync(new Document("fullDocument._partition", "Store 42"));
watcher.get(result -> {
if (result.isSuccess()) {
Log.v("EXAMPLE", "Event type: " +
result.get().getOperationType() + " full document: " +
result.get().getFullDocument());
} else {
Log.e("EXAMPLE",
"failed to subscribe to filtered changes in the collection with : ",
result.getError());
}
});
List<Plant> plants = Arrays.asList(
new Plant(
new ObjectId(),
"triffid",
"low",
"green",
"perennial",
"Store 47"),
new Plant(
new ObjectId(),
"venomous tentacula",
"low",
"brown",
"annual",
"Store 42"
));
mongoCollection.insertMany(plants).getAsync(task -> {
if (task.isSuccess()) {
int insertedCount = task.get().getInsertedIds().size();
Log.v("EXAMPLE", "successfully inserted " +
insertedCount + " documents into the collection.");
} else {
Log.e("EXAMPLE", "failed to insert documents with: ",
task.getError());
}
});
val watcher = mongoCollection
.watchWithFilterAsync(Document("fullDocument._partition", "Store 42"))
watcher[{ result ->
if (result.isSuccess) {
Log.v("EXAMPLE", "Event type: ${result.get().operationType} full document: ${result.get().fullDocument}")
} else {
Log.e("EXAMPLE", "failed to subscribe to filtered changes in the collection with : ${result.error}")
}
}]
val plants = listOf(
Plant(
ObjectId(),
"triffid",
"low",
"green",
"perennial",
"Store 47"
),
Plant(
ObjectId(),
"venomous tentacula",
"low",
"brown",
"annual",
"Store 42"
)
)
mongoCollection.insertMany(plants).getAsync { task ->
if (task.isSuccess) {
val insertedCount = task.get().insertedIds.size
Log.v("EXAMPLE", "successfully inserted $insertedCount documents into the collection.")
} else {
Log.e("EXAMPLE", "failed to insert documents with: ${task.error}")
}
}

Running this snippet produces output resembling the following:

V/EXAMPLE: successfully inserted 2 documents into the collection
V/EXAMPLE: Event type: INSERT full document: Plant [id=5f6bb..., name=venomous tentacula, sunlight=low, color=brown, type=annual, partition=Store 42]

Las operaciones de agregación ejecutan todos los documentos de una colección a través de una serie de etapas de agregación de datos denominadas canalización de agregación. La agregación permite filtrar y transformar documentos, recopilar datos resumidos sobre grupos de documentos relacionados y realizar otras operaciones complejas de datos.

Puede ejecutar una canalización de agregación utilizando collection.aggregate().

Una operación de agregación acepta una lista de etapas de agregación como entrada y devuelve una Tarea que se resuelve en una colección de documentos procesados ​​por la canalización.

Puede utilizar la etapa $match para filtrar documentos según un filtro de consulta de API de consulta.

{
"$match": {
"<Field Name>": <Query Expression>,
...
}
}

Ejemplo

El siguiente filtro de etapa $match filtra documentos para incluir solo aquellos donde el campo type tenga un valor igual a "perenne":

// create an aggregation pipeline
List<Document> pipeline = Arrays.asList(
new Document("$match",
new Document("type",
new Document("$eq", "perennial"))));
// query mongodb using the pipeline
RealmResultTask<MongoCursor<Document>> aggregationTask =
mongoCollection.aggregate(pipeline).iterator();
// handle success or failure of the query
aggregationTask.getAsync(task -> {
if (task.isSuccess()) {
MongoCursor<Document> results = task.get();
// iterate over and print the results to the log
Log.v("EXAMPLE", "successfully aggregated the plants. Results:");
while (results.hasNext()) {
Log.v("EXAMPLE", results.next().toString());
}
} else {
Log.e("EXAMPLE", "failed to aggregate documents with: ",
task.getError());
}
});
// create an aggregation pipeline
val pipeline =
listOf(
Document("\$match",
Document("type",
Document("\$eq", "perennial")
)
)
)
// query mongodb using the pipeline
val aggregationTask = mongoCollection.aggregate(pipeline).iterator()
// handle success or failure of the query
aggregationTask.getAsync { task: App.Result<MongoCursor<Document>> ->
if (task.isSuccess) {
val results = task.get()
// iterate over and print the results to the log
Log.v("EXAMPLE",
"successfully aggregated the plants. Results:")
while (results.hasNext()) {
Log.v("EXAMPLE", results.next().toString())
}
} else {
Log.e("EXAMPLE",
"failed to aggregate documents with: ${task.error}")
}
}

Puede usar la etapa $group para agregar datos de resumen de uno o más documentos. MongoDB agrupa documentos según la expresión definida en el _id valor del campo de la $group etapa. Puede hacer referencia a un campo de documento específico anteponiendo al nombre del $ campo.

The following snippet groups all documents in the plants collection by their type value and aggregates a count of the number of each type:

// create an aggregation pipeline
List<Document> pipeline = Arrays.asList(
new Document("$group", new Document("_id", "$type")
.append("totalCount", new Document("$sum", 1))));
// query mongodb using the pipeline
RealmResultTask<MongoCursor<Document>> aggregationTask =
mongoCollection.aggregate(pipeline).iterator();
// handle success or failure of the query
aggregationTask.getAsync(task -> {
if (task.isSuccess()) {
MongoCursor<Document> results = task.get();
// iterate over and print the results to the log
Log.v("EXAMPLE", "successfully aggregated the plants. Results:");
while (results.hasNext()) {
Log.v("EXAMPLE", results.next().toString());
}
} else {
Log.e("EXAMPLE", "failed to aggregate documents with: ",
task.getError());
}
});
// create an aggregation pipeline
val pipeline =
listOf(
Document("\$group",
Document("_id", "\$type")
.append("totalCount", Document("\$sum", 1))
)
)
// query mongodb using the pipeline
val aggregationTask = mongoCollection.aggregate(pipeline).iterator()
// handle success or failure of the query
aggregationTask.getAsync { task: App.Result<MongoCursor<Document>> ->
if (task.isSuccess) {
val results = task.get()
// iterate over and print the results to the log
Log.v("EXAMPLE",
"successfully aggregated the plants. Results:")
while (results.hasNext()) {
Log.v("EXAMPLE", results.next().toString())
}
} else {
Log.e("EXAMPLE",
"failed to aggregate documents with: ${task.error}")
}
}

Puede usar la etapa $project para incluir u omitir campos específicos de los documentos. Además, puede calcular nuevos campos mediante operadores de agregación. Las proyecciones funcionan de dos maneras:

  • Incluya de forma explícita campos con un valor de 1. Esto tiene el efecto secundario de excluir, de forma implícita, todos los campos no especificados.

  • Implicitly exclude fields with a value of 0. This has the side-effect of implicitly including all unspecified fields.

Estos dos métodos de proyección son mutuamente excluyentes: si incluyes explícitamente campos, no puedes excluir explícitamente campos y viceversa.

Nota

The _id field is a special case: it is always included in every query unless explicitly specified otherwise. For this reason, you can exclude the _id field with a 0 value while simultaneously including other fields, like _partition, with a 1. Only the special case of exclusion of the _id field allows both exclusion and inclusion in one $project stage.

{
"$project": {
"<Field Name>": <0 | 1 | Expression>,
...
}
}

Ejemplo

The following $project stage omits the _id field, includes the name field, and creates a new field named storeNumber. The storeNumber is generated using two aggregation operators:

  1. $split separates the _partition value into two string segments surrounding the space character. For example, the value "Store 42" split in this way returns an array with two elements: "Store" and "42".

  2. $arrayElemAt selects a specific element from an array based on the second argument. In this case, the value 1 selects the second element from the array generated by the $split operator since arrays index from 0. For example, the value ["Store", "42"] passed to this operation would return a value of "42".

// create an aggregation pipeline
List<Document> pipeline = Arrays.asList(
new Document("$project",
new Document("_id", 0)
.append("name", 1)
.append("storeNumber",
new Document("$arrayElemAt",
Arrays.asList(
new Document("$split",
Arrays.asList("$_partition", " ")),
1)))));
// query mongodb using the pipeline
RealmResultTask<MongoCursor<Document>> aggregationTask =
mongoCollection.aggregate(pipeline).iterator();
// handle success or failure of the query
aggregationTask.getAsync(task -> {
if (task.isSuccess()) {
MongoCursor<Document> results = task.get();
// iterate over and print the results to the log
Log.v("EXAMPLE", "successfully aggregated the plants. Results:");
while (results.hasNext()) {
Log.v("EXAMPLE", results.next().toString());
}
} else {
Log.e("EXAMPLE", "failed to aggregate documents with: ",
task.getError());
}
});
// create an aggregation pipeline
val pipeline =
listOf(
Document("\$project",
Document("_id", 0)
.append("name", 1)
.append("storeNumber",
Document("\$arrayElemAt",
listOf(
Document("\$split",
listOf(
"\$_partition",
" "
)
),
1
)
)
)
)
)
// query mongodb using the pipeline
val aggregationTask = mongoCollection.aggregate(pipeline).iterator()
// handle success or failure of the query
aggregationTask.getAsync { task: App.Result<MongoCursor<Document>> ->
if (task.isSuccess) {
val results = task.get()
// iterate over and print the results to the log
Log.v("EXAMPLE",
"successfully aggregated the plants. Results:")
while (results.hasNext()) {
Log.v("EXAMPLE", results.next().toString())
}
} else {
Log.e("EXAMPLE",
"failed to aggregate documents with: ${task.error}")
}
}

Puedes utilizar la etapa $addFields para añadir nuevos campos con valores calculados utilizando operadores de agregación.

Nota

$addFields es similar a $project pero no te permite incluir ni omitir campos.

Ejemplo

The following $addFields stage creates a new field named storeNumber where the value is the output of two aggregate operators that transform the value of the _partition field.

// create an aggregation pipeline
List<Document> pipeline = Arrays.asList(
new Document("$addFields",
new Document("storeNumber",
new Document("$arrayElemAt", Arrays.asList(
new Document("$split", Arrays.asList(
"$_partition", " ")), 1)))));
// query mongodb using the pipeline
RealmResultTask<MongoCursor<Document>> aggregationTask =
mongoCollection.aggregate(pipeline).iterator();
// handle success or failure of the query
aggregationTask.getAsync(task -> {
if (task.isSuccess()) {
MongoCursor<Document> results = task.get();
// iterate over and print the results to the log
Log.v("EXAMPLE", "successfully aggregated the plants. Results:");
while (results.hasNext()) {
Log.v("EXAMPLE", results.next().toString());
}
} else {
Log.e("EXAMPLE", "failed to aggregate documents with: ",
task.getError());
}
});
// create an aggregation pipeline
val pipeline =
listOf(
Document("\$addFields",
Document("storeNumber",
Document("\$arrayElemAt",
listOf(
Document("\$split",
listOf(
"\$_partition",
" "
)
),
1
)
)
)
)
)
// query mongodb using the pipeline
val aggregationTask = mongoCollection.aggregate(pipeline).iterator()
// handle success or failure of the query
aggregationTask.getAsync { task: App.Result<MongoCursor<Document>> ->
if (task.isSuccess) {
val results = task.get()
// iterate over and print the results to the log
Log.v("EXAMPLE",
"successfully aggregated the plants. Results:")
while (results.hasNext()) {
Log.v("EXAMPLE", results.next().toString())
}
} else {
Log.e("EXAMPLE",
"failed to aggregate documents with: ${task.error}")
}
}

You can use the $unwind stage to transform a single document containing an array into multiple documents containing individual values from that array. When you unwind an array field, MongoDB copies each document once for each element of the array field but replaces the array value with the array element in each copy.

{
$unwind: {
path: <Array Field Path>,
includeArrayIndex: <string>,
preserveNullAndEmptyArrays: <boolean>
}
}

Ejemplo

La siguiente etapa $unwind crea un documento nuevo para cada elemento del arreglo items en cada documento. También agrega un campo llamado itemIndex a cada nuevo documento que especifica el índice de posición del elemento en el arreglo original:

// create an aggregation pipeline
List<Document> pipeline = Arrays.asList(
new Document("$unwind", new Document("path", "$items")
.append("includeArrayIndex", "itemIndex")));
// query mongodb using the pipeline
RealmResultTask<MongoCursor<Document>> aggregationTask = mongoCollection.aggregate(pipeline).iterator();
// handle success or failure of the query
aggregationTask.getAsync(task -> {
if (task.isSuccess()) {
MongoCursor<Document> results = task.get();
// iterate over and print the results to the log
Log.v("EXAMPLE", "successfully aggregated the plants. Results:");
while (results.hasNext()) {
Log.v("EXAMPLE", results.next().toString());
}
} else {
Log.e("EXAMPLE", "failed to aggregate documents with: ",
task.getError());
}
});
// create an aggregation pipeline
val pipeline =
listOf(
Document("\$unwind", Document("path", "\$items")
.append("includeArrayIndex", "itemIndex"))
)
// query mongodb using the pipeline
val aggregationTask = mongoCollection.aggregate(pipeline).iterator()
// handle success or failure of the query
aggregationTask.getAsync { task: App.Result<MongoCursor<Document>> ->
if (task.isSuccess) {
val results = task.get()
// iterate over and print the results to the log
Log.v("EXAMPLE",
"successfully aggregated the plants. Results:")
while (results.hasNext()) {
Log.v("EXAMPLE", results.next().toString())
}
} else {
Log.e("EXAMPLE",
"failed to aggregate documents with: ${task.error}")
}
}

Consideremos el siguiente documento de una colección de compras:

{
_id: 123,
customerId: 24601,
items: [
{ name: "Baseball", quantity: 5 },
{ name: "Baseball Mitt", quantity: 1 },
{ name: "Baseball Bat", quantity: 1 },
]
}

Si aplicamos la etapa de ejemplo $unwind a este documento, la etapa produce los siguientes tres documentos:

{
_id: 123,
customerId: 24601,
itemIndex: 0,
items: { name: "Baseball", quantity: 5 }
}, {
_id: 123,
customerId: 24601,
itemIndex: 1,
items: { name: "Baseball Mitt", quantity: 1 }
}, {
_id: 123,
customerId: 24601,
itemIndex: 2,
items: { name: "Baseball Bat", quantity: 1 }
}

Volver

Llamar a una función