MongoDB Reactive Streams Driver Quick Start - POJOs

Note

POJOs stands for Plain Old Java Objects.

The following code snippets come from the PojoQuickTour.java example code that can be found with the driver source on github.

important

This guide uses the Subscriber implementations as covered in the Quick Start Primer.

Prerequisites

  • A running MongoDB on localhost using the default port for MongoDB 27017

  • MongoDB Reactive Streams Driver. See Installation for instructions on how to install the MongoDB driver.

  • Quick Start. This guide follows on from the Quick Start.

  • The following import statements:

import com.mongodb.client.result.InsertOneResult;
import com.mongodb.client.result.InsertManyResult;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.mongodb.reactivestreams.client.MongoClient;
import com.mongodb.reactivestreams.client.MongoClients;
import com.mongodb.reactivestreams.client.MongoCollection;
import com.mongodb.reactivestreams.client.MongoDatabase;

import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;

import java.util.List;

import static com.mongodb.client.model.Filters.*;
import static com.mongodb.client.model.Updates.*;
import static java.util.Arrays.asList;
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;
  • The following POJO classes. The full source is available on github for the Person and Address POJOs. Here are the main implementation details:
public final class Person {
    private ObjectId id;
    private String name;
    private int age;
    private Address address;

    public Person() {
    }

    public ObjectId getId() {
        return id;
    }

    public void setId(final ObjectId id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(final String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(final int age) {
        this.age = age;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(final Address address) {
        this.address = address;
    }
    
    // Rest of implementation
}

public final class Address {
    private String street;
    private String city;
    private String zip;

    public Address() {
    }

    public String getStreet() {
        return street;
    }

    public void setStreet(final String street) {
        this.street = street;
    }

    public String getCity() {
        return city;
    }

    public void setCity(final String city) {
        this.city = city;
    }

    public String getZip() {
        return zip;
    }

    public void setZip(final String zip) {
        this.zip = zip;
    }
    
    // Rest of implementation
}

Creating a Custom CodecRegistry

Before you can use a POJO with the driver, you need to configure the CodecRegistry to include a codecs to handle the translation to and from bson for your POJOs. The simplest way to do that is to use the PojoCodecProvider.builder() to create and configure a CodecProvider.

The following example will combine the default codec registry, with the PojoCodecProvider configured to automatically create POJO Codecs:

CodecRegistry pojoCodecRegistry = fromRegistries(MongoClientSettings.getDefaultCodecRegistry(),
                fromProviders(PojoCodecProvider.builder().automatic(true).build()));
Note

The registries are checked in order until one returns a codec for the requested class. The DefaultCodecRegistry should be first in the list, and the PojoCodecProvider should always be the last CodecProvider since it can provide a codec for almost any class.

Using the CodecRegistry

There are multiple ways to set the pojoCodecRegistry for use:

  • You can set it when instantiating a MongoClient object:
MongoClientSettings settings = MongoClientSettings.builder()
        .codecRegistry(pojoCodecRegistry)
        .build();
MongoClient mongoClient = MongoClients.create(settings);
  • You can use an alternative CodecRegistry with a MongoDatabase:
database = database.withCodecRegistry(pojoCodecRegistry);
  • You can use an alternative CodecRegistry with a MongoCollection:
collection = collection.withCodecRegistry(pojoCodecRegistry);

Inserting a POJO into MongoDB

The codec registry will automatically try to create a POJO Codec for unknown classes. This allows you to use POJOs out of the box without any extra configuration. See the Bson POJO page for information on configuring POJO Codecs.

Before you can insert a POJO into MongoDB, you need a MongoCollection instance configured with the Pojo’s type:

MongoCollection<Person> collection = database.getCollection("people", Person.class);

Insert a Person

To insert a Person into the collection, you can use the collection’s insertOne() method.

Person ada = new Person("Ada Byron", 20, new Address("St James Square", "London", "W1"));

collection.insertOne(ada).subscribe(new OperationSubscriber<InsertOneResult>());

Insert Many Persons

To add multiple Person instances, you can use the collection’s insertMany() method which takes a list of Person.

The following example will add multiple Person instances into the collection:

List<Person> people = asList(
        new Person("Charles Babbage", 45, new Address("5 Devonshire Street", "London", "W11")),
        new Person("Alan Turing", 28, new Address("Bletchley Hall", "Bletchley Park", "MK12")),
        new Person("Timothy Berners-Lee", 61, new Address("Colehill", "Wimborne", null))
);

collection.insertMany(people).subscribe(new OperationSubscriber<InsertManyResult>());

Query the Collection

To query the collection, you can use the collection’s find() method.

The following example prints all the Person instances in the collection:

collection.find().subscribe(new PrintToStringSubscriber<>());

The example will eventually output the following:

Person{id='591dbc2550852fa685b3ad17', name='Ada Byron', age=20, address=Address{street='St James Square', city='London', zip='W1'}}
Person{id='591dbc2550852fa685b3ad18', name='Charles Babbage', age=45, address=Address{street='5 Devonshire Street', city='London', zip='W11'}}
Person{id='591dbc2550852fa685b3ad19', name='Alan Turing', age=28, address=Address{street='Bletchley Hall', city='Bletchley Park', zip='MK12'}}
Person{id='591dbc2550852fa685b3ad1a', name='Timothy Berners-Lee', age=61, address=Address{street='Colehill', city='Wimborne', zip='null'}}

Specify a Query Filter

To query for Person instance that match certain conditions, pass a filter object to the find() method. To facilitate creating filter objects, the Java driver provides the Filters helper.

important

When querying POJOs you must query against the document field name and not the Pojo’s property name. By default they are the same but it is possible to change how POJO property names are mapped.

Get A Single Person That Matches a Filter

For example, to find the first Person in the database that lives in Wimborne pass an eq filter object to specify the equality condition:

collection.find(eq("address.city", "Wimborne")).first().subscribe(new PrintToStringSubscriber<>());

The example prints one document:

Person{id='591dbc2550852fa685b3ad1a', name='Timothy Berners-Lee', age=61, 
       address=Address{street='Colehill', city='Wimborne', zip='null'}}

Get All Person Instances That Match a Filter

The following example prints ever document where "age" > 30:

collection.find(gt("age", 30)).subscribe(new PrintToStringSubscriber<>());

Update Documents

To update documents in a collection, you can use the collection’s updateOne and updateMany methods.

Pass to the methods:

  • A filter object to determine the document or documents to update. To facilitate creating filter objects, the Java driver provides the Filters helper. To specify an empty filter (i.e. match all Persons in a collection), use an empty Document object.

  • An update document that specifies the modifications. For a list of the available operators, see update operators.

The update methods return an UpdateResult which provides information about the operation including the number of documents modified by the update.

Update a Single Person

To update at most a single Person, use the updateOne method.

The following example updates Ada Byron setting their age to 23 and name to Ada Lovelace:

collection.updateOne(eq("name", "Ada Byron"), combine(set("age", 23), set("name", "Ada Lovelace")))
        .subscribe(new OperationSubscriber<>());

Update Multiple Persons

To update all Persons that match a filter, use the updateMany method.

The following example sets the zip field to null for all documents that have a zip value:

collection.updateMany(not(eq("zip", null)), set("zip", null))
        .subscribe(new OperationSubscriber<>());

Replace a Single Person

An alternative method to change an existing Person, would be to use the replaceOne method.

The following example replaces the Ada Lovelace back to the original document:

collection.replaceOne(eq("name", "Ada Lovelace"), ada).subscribe(new OperationSubscriber<>());

Delete Documents

To delete documents from a collection, you can use the collection’s deleteOne and deleteMany methods.

Pass to the methods a filter object to determine the document or documents to delete. To facilitate creating filter objects, the Java driver provides the Filters helper. To specify an empty filter (i.e. match all documents in a collection), use an empty Document object.

The delete methods return a DeleteResult which provides information about the operation including the number of documents deleted.

Delete a Single Person That Matches a Filter

To delete at most a single Person that matches a filter, use the deleteOne method:

The following example deletes at most one Person who lives in Wimborne:

collection.deleteOne(eq("address.city", "Wimborne")).subscribe(new OperationSubscriber<>());

Delete All Persons That Match a Filter

To delete multiple Persons matching a filter use the deleteMany method.

The following example deletes all Persons that live in London:

collection.deleteMany(eq("address.city", "London")).subscribe(new OperationSubscriber<>());

Additional Information

For additional information about the configuring the PojoCodecProvider, see the Bson POJO page.

For additional tutorials about using MongoDB (such as to use the aggregation framework, specify write concern, etc.), see Java Driver Tutorials.