Interactive FerretDB Tutorial

This is an interactive version of the How to Pass Basic MongoDB CRUD Operations With FerretDB tutorial by Alexander Fashakin of the FerretDB team, licensed under Apache License 2.0.

FerretDB is an open-source drop-in replacement for MongoDB that uses PostgreSQL or SQLite as a backend. With FerretDB, there's no need to learn new syntax or query methods. You can use the familiar MongoDB query language or driver API.

This blog post will show you how to perform basic MongoDB CRUD operations using FerretDB.

Perform MongoDB CRUD operations with FerretDB

CRUD (Create, Read, Update, and Delete) operations are at the heart of any database management system. They allow users to easily interact with the database to create, sort, filter, modify, or delete records.

For users looking for an open-source MongoDB alternative, FerretDB offers a direct replacement that still allows you to use all your favorite MongoDB CRUD methods and commands, without having to learn entirely new commands.

How to set up FerretDB database

To set up FerretDB locally, you can install it using Docker or the .deb and .rpm packages available for each release. Follow the quick start on Github to get started. Or just keep reading this blog post - you can try different examples in a playground without leaving the browser.

As with MongoDB, you can view the list of databases in FerretDB using the show dbs command. The use command allows you to switch from one database to another. If the database does not exist, FerretDB will create a new one:

use league

Since there is no existing database with this name, a new database (league) is created in your FerretDB storage backend (PostgreSQL or SQLite depending on your configuration).

Create operation

Similar to MongoDB, FerretDB provides the insertOne() and insertMany() methods for adding new records to a collection.

insertOne()

Using the database we created earlier, let's insert a single document record with fields and values into the collection by calling the insertOne() method. The syntax for this operation is as follows:

db.collection_name.insertOne({field1: value1, field2: value2, ...fieldN: valueN})

The process is identical to adding a single data record in MongoDB. Let's start by adding a single team to the league:

db.league.insertOne({
    club: "PSG",
    points: 30,
    average_age: 30,
    discipline: { red: 5, yellow: 30 },
    qualified: false,
});

This command creates a new document in the collection. If the operation is successful, you'll get a response with acknowledged equal to true, and the ID of the inserted document (insertedID) containing the ObjectId.

Note that if a collection does not exist, the insert command will automatically create one for you.

insertMany()

Instead of creating just a single document in the collection, you can create multiple documents using the insertMany() method. Indicate that you are inserting multiple document records with square brackets, and separate each document with commas:

db.collection_name.insertMany([{ document1 }, { document2 }, ...{ documentN }]);

To see how this works, let's add three more teams to the league:

db.league.insertMany([
    {
        club: "Arsenal",
        points: 80,
        average_age: 24,
        discipline: { red: 2, yellow: 15 },
        qualified: true,
    },
    {
        club: "Barcelona",
        points: 60,
        average_age: 31,
        discipline: { red: 0, yellow: 7 },
        qualified: false,
    },
    {
        club: "Bayern",
        points: 84,
        average_age: 29,
        discipline: { red: 1, yellow: 20 },
        qualified: true,
    },
]);

Now we have 4 teams in the league: Arsenal, Barcelona, Bayern and PSG.

Read operation

Read operations in FerretDB are similar to those in MongoDB. We'll explore two basic methods for querying records in a collection: find() and findOne().

find()

In each read operation, you must filter the documents according to some criteria. The find() method filters and selects all the documents in a collection that match the query parameters.

First, let's select all the teams in the league:

db.league.find({});

With an empty query parameter, the method returns all documents in the league collection.

Now, let's add a query parameter to the find() operation to filter for a specific team:

db.league.find({ club: "PSG" });

You can also filter a collection in FerretDB using any of the common MongoDB operators:

  • $eq: select records that are equal to a specific value
  • $ne: not equal to a specific value
  • $gt: greater than a specific value
  • $lt: less than a specific value
  • $gte: greater or equal to a specific value
  • $lte: less than or equal to a specific value
  • $in: records that contain any of the values in a given array
  • $nin: records that do not contain any of the values in a given array

Find documents using the $in operator

Suppose we want to query the collection for documents that contain any of the values present in an array. To do this, we'll filter the document using an array of values with the $in operator:

db.collection_name.find({ field: { $in: [<value1>, <value2>, ... <valueN> ] } })

Let's filter the league data for teams with 80 or 60 points:

db.league.find({ points: { $in: [80, 60] } });

That would be Arsenal and Barcelona.

Find documents using the $lt operator

The $lt operator filters a collection for records that are less than a specified value. For example, let's select the documents with less than 60 points:

db.league.find({ points: { $lt: 60 } });

It seems that PSG is not doing so well.

findOne()

The findOne() method selects the first document that matches a given set of query parameters. For example, let's filter by qualified teams:

db.league.findOne({ qualified: true });

Even though two documents match this query (Arsenal and Bayern), findOne only returns the first one (Arsenal).

Update operation

Update operations are write commands that accept a query parameter and changes to be applied to a document.

We will explore three basic MongoDB methods for updating documents using FerretDB: updateOne(), updateMany(), and replaceOne().

updateOne()

The updateOne() method uses a query parameter to filter and then update a single document in a collection. The following syntax represents the update operation, where the atomic operator $set contains the new record:

db.collection_name.updateOne({<query-params>}, {$set: {<update fields>}})

Let's increase the number of points for the PSG team to 35 (not that it helps, honestly):

db.league.updateOne({ club: "PSG" }, { $set: { points: 35 } });

This update operation only affects the first document that's retrieved from the collection. If the operation is successful, the queried document is updated (modifiedCount equals to 1).

updateMany()

The updateMany() method can take a query and update many documents at once. For example, let's treat all teams with less than 90 points as not qualified:

db.league.updateMany({ points: { $lte: 90 } }, { $set: { qualified: false } });

According to the matchedCount = 4, the filtering part of the command selected all our teams. And since modifiedCount = 2, the only two previously qualified teams (Arsenal and Bayern) are no longer qualified. This leaves us with no qualified teams at all.

replaceOne()

The replaceOne() method is ideal if you intend to replace an entire document at once.

db.league.replaceOne(
    { club: "Barcelona" },
    {
        club: "Inter",
        points: 83,
        average_age: 32,
        discipline: { red: 2, yellow: 10 },
        qualified: true,
    }
);

Inter replaces Barcelona...

db.league.find({ qualified: true });

... and becomes the only qualified team in the league.

Delete operation

The delete operations only affect a single collection. Let's look at two methods for deleting documents: deleteOne() and deleteMany().

deleteOne()

The deleteOne() method takes in a query parameter that filters a collection for a particular document and then deletes it.

Let's get rid of Arsenal:

db.league.deleteOne({ club: "Arsenal" });

Note that this operation deletes only the first document that matches the query.

deleteMany()

The deleteMany() method is used to delete multiple documents in a collection. The operation takes a query, then filters and deletes all documents that match the query.

Let's remove all non-qualifying teams from the league:

db.league.deleteMany({ qualified: false });

Two more teams are deleted. Where does that leave us? Let's find out:

db.league.find({});

So the only one left is Inter. Good for them!

Get started with FerretDB

Voila! Exactly the MongoDB replacement you've been looking for.

Beyond the basic CRUD operations covered in this post, you can perform more complex MongoDB commands without reinventing the wheel, learning new commands, or giving up the power of using open-source software.

FerretDB serves as a truly open-source replacement for MongoDB. This means you don't have to sacrifice the integrity and benefits of open-source software, while still enjoying the benefits of a non-relational NoSQL database.

To learn more about the importance of an open-source alternative to MongoDB, read this article.

──

Interactive examples in this post are powered by codapi — an open source tool I'm building. Use it to embed live code snippets into your product docs, online course or blog.

★ Subscribe to keep up with new posts.