Menu Docs
Página inicial do Docs
/ /
Atlas Device SDKs
/ /

Query MongoDB - Java SDK

Nesta página

  • Casos de uso
  • Pré-requisitos
  • Configurar seu projeto
  • Configurar seu projeto
  • Vincular um Cluster de Serviço do Atlas do MongoDB
  • Importar dependências de domínio
  • Instanciar um identificador de coleção do MongoDB
  • Dados de exemplo
  • Criar documentos
  • Inserir um único documento
  • Insira vários documentos
  • Ler documentos
  • Encontrar um único documento
  • Localizar vários documentos
  • Contagem de documentos na coleção
  • Atualize documentos
  • Atualizar um único documento
  • Atualizar vários documentos
  • Documentos do Upsert
  • Exclua documentos
  • Excluir um único documento
  • Excluir vários documentos
  • Fique atento às mudanças
  • Fique atento às mudanças em uma coleção
  • Fique atento às alterações em uma coleção com um filtro
  • Agregar documentos em uma coleção
  • Filtrar documentos
  • Documentos do grupo
  • Campos do documento do projeto
  • Adicionar campos aos documentos
  • Unwind Array Values

Você pode fazer query dos dados armazenados no MongoDB Atlas diretamente do código do seu aplicação Android usando o MongoClient do Realm Java SDK com aAPI de query . O Atlas App Services fornece regras de acesso a dados em coleções para recuperar resultados com segurança com base no usuário conectado ou no conteúdo de cada documento.

As seguintes ações permitem o acesso a um MongoDB Atlas cluster vinculado a partir de um aplicativo Android usando o Realm SDK.

Observação

Cada operação descrita nesta página usa uma query para corresponder a determinados documentos na coleção na qual a operação é executada. Quando um filtro corresponde a vários documentos em uma coleção, eles são retornados em uma ordem indeterminada a menos que você especifique um parâmetro de classificação. Isto significa que, se você não especificar uma classificação para as funções findOne(), updateOne() ou deleteOne() , sua operação poderá corresponder a qualquer documento que corresponda à query. Para mais informações sobre classificação, consulte cursor.sort().

Existem várias razões pelas quais você pode querer fazer uma query em uma fonte de dados MongoDB. Trabalhar com dados em seu cliente via Atlas Device Sync nem sempre é prático ou possível. Talvez você queira fazer uma query no MongoDB quando:

  • O conjunto de dados for grande ou o dispositivo cliente tiver restrições para carregar todo o conjunto de dados

  • Você estiver criando ou atualizando dados de usuário personalizados

  • Você estiver recuperando documentos que não sejam modelados no Realm

  • Sua aplicação precisa acessar collections que não têm esquemas rigorosos

  • Um serviço que não é do Realm gera coleções que você deseja acessar

Embora não exaustivos, esses são alguns casos de uso comuns para a query direta do MongoDB.

Antes de poder executar uma query do MongoDB a partir do seu aplicativo Android, você deve configurar o MongoDB Data Access no seu App Services App. Para saber como configurar seu aplicativo de backend para permitir que o Realm SDK consulte o Atlas, consulte Configurar o acesso aos dados do MongoDB na documentação do Atlas App Services .

1

Siga as etapas no guia Instalar o Realm Java SDK .

2

Siga as etapas no guia Vincular uma fonte de dados do MongoDB . Atribua um nome significativo ao seu serviço -- você precisará dele para se conectar ao cluster usando o SDK do Realm.

3

Para operações CRUD em uma coleção MongoDB remota, você usará uma ou mais das seguintes declarações do import :

// 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 se conectar a uma instância do MongoDB, você precisará de um usuário com acesso a uma coleção MongoDB. Faça login em seu aplicativo como usuário e use o código a seguir para instanciar um identificador de coleção MongoDB local.

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")

Observação

Usando classes personalizadas com MongoDB

Para usar classes diferentes da classe Document integrada com o MongoDB, você pode adicionar codecs às suas instâncias MongoCollection . No exemplo acima, adicionamos PojoCodecProvider para suportar objetos Java antigos e simples (POJOs). O suporte a objetos personalizados requer dois fornecedores de codec:

  • o provedor de codec padrão, que fornece suporte para tipos Java integrados (acessados por meio de AppConfiguration.DEFAULT_BSON_CODEC_REGISTRY)

  • PojoCodecProvider, que cria automaticamente novos codecs para dar suporte a classes POJO

O SDK verifica os registros em ordem até que um retorne um codec para a classe solicitada. Como resultado, você deve listar o registro de codec padrão primeiro e o PojoCodecProvider deve sempre ser o último CodecProvider, pois ele pode fornecer um codec para quase qualquer classe.

Os exemplos a seguir operam em uma coleção MongoDB que descreve o inventário em uma cadeia de lojas de plantas. Considere a seguinte coleção de documentos descrevendo várias plantas para venda em uma loja:

Plan.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.");
Plante.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.")

Esses trechos de código demonstram como inserir um ou mais documentos em uma coleção MongoDB de um aplicativo móvel. As operações de inserção recebem um documento ou documentos a serem adicionados ao MongoDB como argumento e retornam um RealmResultTask que resulta em um objeto que contém os resultados da execução da operação.

Você pode inserir um único documento usando collection.insertOne().

O trecho a seguir insere um único documento que descreve uma planta "lírio do vale" em uma coleção de documentos que descrevem plantas à venda em um grupo de lojas:

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}")
}
}

A execução deste trecho produz saída semelhante ao seguinte:

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

Você pode inserir vários documentos ao mesmo tempo usando collection.insertMany().

O trecho a seguir insere três documentos descrevendo plantas em uma coleção de documentos que descrevem plantas para venda em um grupo de lojas:

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}")
}
}

A execução deste trecho produz saída semelhante ao seguinte:

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

Esses trechos de código demonstram como ler dados armazenados em uma coleção MongoDB de um aplicação móvel. As operações de leitura utilizam queries para especificar quais documentos devem ser retornados do banco de banco de dados. As operações de leitura retornam uma tarefa que resulta em um único documento correspondente (no caso de findOne()), um long valor numérico (no caso de count()) ou um iterador que permite percorrer a coleção de documentos correspondentes (no caso de find()).

Você pode encontrar um único documento usando collection.findOne().

O trecho a seguir encontra um único documento de uma coleção de documentos que descrevem plantas para venda em um grupo de lojas onde o campo type do documento da planta contém o valor da string "perennial":

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}")
}
}

A execução deste trecho produz uma saída semelhante ao seguinte:

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

Você pode encontrar vários documentos usando collection.find().

O snippet a seguir encontra todos os documentos em uma coleção de documentos que descrevem plantas à venda em um grupo de lojas que contêm um campo chamado _partition com um valor de "Loja 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}")
}
}

A execução deste trecho produz saída semelhante ao seguinte:

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]

Você pode contar documentos em uma coleção usando collection.count(). Você pode especificar uma query opcional para determinar quais documentos contar. Se você não especificar uma query, a ação contará todos os documentos da coleção.

O seguinte trecho conta o número de documentos em uma coleção de documentos que descrevem plantas para venda em um grupo de lojas:

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}")
}
}

A execução deste trecho produz saída semelhante ao seguinte:

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

Esses trechos de código demonstram como atualizar os dados armazenados em uma coleção MongoDB de um aplicativo móvel. As operações de atualização usam queries para especificar quais documentos atualizar e atualizar os operadores para descrever como mutar documentos que correspondem à query. Atualizar operações retornam uma Tarefa que se resolve para um objeto que contém os resultados da execução da operação.

Você pode atualizar um único documento usando collection.updateOne().

O trecho a seguir atualiza um único documento em uma coleção de documentos que descrevem plantas para venda em um grupo de lojas. Essa operação consulta um documento em que o campo name contém o valor "petunia" e altera o valor do campo sunlight do primeiro documento correspondente para "parcial":

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}")
}
}

A execução deste trecho produz saída semelhante ao seguinte:

V/EXAMPLE: successfully updated a document.

Você pode atualizar vários documentos usando collection.updateMany().

O trecho a seguir atualiza vários documentos em uma coleção de documentos que descrevem plantas para venda em um grupo de lojas. Esta operação faz queries em documentos onde o campo _partition contém o valor "Armazenar 47" e altera o valor do campo _partition de cada documento correspondente para "Armazenar 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}")
}
}

A execução deste trecho produz saída semelhante ao seguinte:

V/EXAMPLE: successfully updated 2 documents.

Se uma operação de atualização não corresponder a nenhum documento na coleção, você poderá inserir automaticamente um único novo documento na coleção que corresponda à query de atualização definindo a opção upsert como true.

O trecho a seguir atualiza um documento em uma coleção de documentos que descrevem plantas para venda em um grupo de lojas ou insere um novo documento se nenhum documento corresponder à query. Esta operação query documentos onde:

  • o campo sunlight tem um valor de "completo"

  • o campo type tem um valor de "perene"

  • o campo color tem um valor de "verde"

  • o campo _partition tem um valor de "Armazenar 47"

Como esse trecho define a opção upsert como true, se nenhum documento corresponder à query, o MongoDB cria um novo documento que inclui a query e as atualizações especificadas:

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}")
}
}

A execução deste trecho produz saída semelhante ao seguinte:

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

Esses trechos de código demonstram como excluir documentos armazenados em uma coleção MongoDB de um aplicativo móvel. As operações de exclusão usam uma query para especificar quais documentos devem ser excluídos e retornam uma tarefa que se resolve para um objeto que contém os resultados da execução da operação.

Você pode excluir um único documento de uma coleção usando collection.deleteOne().

O trecho a seguir exclui um documento em uma coleção de documentos que descrevem plantas para venda em um grupo de lojas. Esta operação consulta um documento onde o campo color tem um valor de "verde" e exclui o primeiro documento que corresponde à consulta:

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}")
}
}

A execução deste trecho produz saída semelhante ao seguinte:

V/EXAMPLE: successfully deleted a document.

Você pode excluir vários itens de uma coleção usando collection.deleteMany().

O trecho a seguir exclui todos os documentos em uma coleção de documentos que descrevem plantas para venda em um grupo de lojas que correspondem à query que corresponde a documentos contendo um valor de campo sunlight de "completo" e um valor de campo type de "anual ".

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}")
}
}

A execução deste trecho produz saída semelhante ao seguinte:

V/EXAMPLE: succcessfully deleted 2 documents.

Estes trechos de código demonstram como configurar e executar operações de observação em uma coleção.

Importante

Limitações sem servidor

Você não poderá observar alterações se a fonte de dados for uma instância sem servidor do Atlas. Atualmente, o MongoDB serverless não oferece suporte a fluxos de alterações, que são usados em coleções monitoradas para escutar alterações.

Você pode abrir um fluxo de alterações feitas em uma coleção chamando collection.watch() ou collection.watchAsync(). Você pode observar alterações em documentos específicos em uma coleção passando as IDs de objeto dos objetos que você gostaria de monitorar como um número variável de argumentos.

O seguinte trecho observa alterações em quaisquer documentos na coleção plants :

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}")
}
}

A execução deste trecho produz saída semelhante ao seguinte:

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]

Você pode abrir um fluxo de alterações feitas em documentos em uma coleção que atendam a determinados critérios chamando collection.watchWithFilter() ou collection.watchWithFilterAsync(). Ambos os métodos aceitam um parâmetro Document ou BsonDocument que é usado como query de um operador $match para processar cada evento de banco de dados que ocorre enquanto observa a coleção.

O trecho a seguir observa alterações em documentos na coleção plants, mas somente o Atlas Triggers a chamada de resposta fornecida para eventos correspondentes a documentos pertencentes à partição chamada "Armazenar 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}")
}
}

A execução deste trecho produz saída semelhante ao seguinte:

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]

As operações de agregação executam todos os documentos em uma coleção por meio de uma série de estágios de agregação de dados chamados de pipeline de agregação. A agregação permite filtrar e transformar documentos, coletar dados resumidos sobre grupos de documentos relacionados e outras operações de dados complexas.

Você pode executar um pipeline de agregação usando collection.aggregate().

Uma operação de aggregation aceita uma lista de estágios de aggregation como entrada e retorna uma Tarefa que resulta em uma coleção de documentos processados pelo pipeline.

Você pode usar o estágio $match para filtrar documentos de acordo com um filtro de query da API de query.

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

Exemplo

O seguinte estágio $match filtra os documentos para incluir apenas aqueles em que o campo type tem um valor igual a "perene":

// 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}")
}
}

Você pode usar o estágio $group para agregar dados resumidos de um ou mais documentos. O MongoDB agrupa documentos com base na expressão definida no valor de campo _id $group do estágio . Você pode referenciar um campo de documento específico prefixando o nome do campo com um $.

O trecho a seguir agrupa todos os documentos na coleção plants por seu valor type e agrega uma contagem do número de cada tipo:

// 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}")
}
}

Você pode usar o estágio $project para incluir ou omitir campos específicos dos documentos. Além disso, você pode calcular novos campos utilizando operadores de aggregation. As projeções funcionam de duas formas:

  • Inclua campos explicitamente com um valor de 1. Isso tem o efeito colateral de excluir implicitamente todos os campos não especificados.

  • Exclua campos de forma implícita com um valor de 0. Isso tem o efeito colateral de incluir implicitamente todos os campos não especificados.

Esses dois métodos de projeção são mutuamente exclusivos: se você incluir campos explicitamente, não poderá excluir campos explicitamente e vice-versa.

Observação

O campo _id é um caso especial: ele é sempre incluído em todas as consultas, a menos que seja explicitamente especificado de outra forma. Por esse motivo, você pode excluir o campo _id com um valor 0 e, ao mesmo tempo, incluir outros campos, como _partition, com um 1. Somente o caso especial de exclusão do campo _id permite tanto a exclusão quanto a inclusão em um estágio $project .

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

Exemplo

O estágio $project a seguir omite o campo _id, inclui o campo name e cria um novo campo chamado storeNumber. O storeNumber é gerado usando dois operadores de agregação:

  1. $split separa o valor _partition em dois segmentos de string ao redor do caractere de espaço. Por exemplo, o valor "Store 42" dividido dessa forma retorna uma matriz com dois elementos: "Store" e "42".

  2. $arrayElemAt seleciona um elemento específico de uma matriz com base no segundo argumento. Nesse caso, o valor 1 seleciona o segundo elemento da matriz gerada pelo operador $split, já que as matrizes são indexadas a partir de 0. Por exemplo, o valor ["Loja", "42"] passado para esta operação retornaria um valor de "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}")
}
}

Você pode usar o estágio $addFields para adicionar novos campos com valores calculados usando operadores de agregação.

Observação

$addFields é semelhante ao $project, mas não permite que você inclua ou omita campos.

Exemplo

O estágio $addFields a seguir cria um novo campo chamado storeNumber em que o valor é a saída de dois operadores agregados que transformam o valor do campo _partition.

// 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}")
}
}

Você pode usar o estágio $unwind para transformar um único documento contendo uma matriz em vários documentos contendo valores individuais dessa matriz. Quando você desenrola um campo de matriz, o MongoDB copia cada documento uma vez para cada elemento do campo de matriz, mas substitui o valor da matriz pelo elemento da matriz em cada cópia.

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

Exemplo

A etapa $unwind a seguir cria um novo documento para cada elemento da array items em cada documento. Ele também adiciona um campo chamado itemIndex a cada novo documento que especifica o índice de posição do elemento na array 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}")
}
}

Considere o seguinte documento de uma collection de compras:

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

Se aplicarmos o exemplo do estágio $unwind a este documento, o estágio produzirá os três documentos a seguir:

{
_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 }
}

Voltar

Chamar uma função