Operating MongoDB databases in C language primarily relies on the official libmongoc driver library (MongoDB C Driver). It provides a complete API supporting core operations such as connection, CRUD, aggregation, and more. The following systematically explains the interaction between C language and MongoDB, from environment setup and basic operations to advanced applications.
Environment Preparation: Installing libmongoc
Installing Dependencies
libmongoc depends on the following libraries (using Ubuntu as an example):
sudo apt-get install -y build-essential pkg-config libssl-dev libsasl2-dev
Installing libmongoc
Install via source compilation (recommended to use the latest stable version, such as 1.24.x):
# Download source code
wget https://github.com/mongodb/mongo-c-driver/releases/download/1.24.3/mongo-c-driver-1.24.3.tar.gz
tar xzf mongo-c-driver-1.24.3.tar.gz
cd mongo-c-driver-1.24.3
# Configure, compile, and install
./configure --enable-tests=no --enable-examples=no
make
sudo make install
# Refresh dynamic library cache
sudo ldconfig
Verifying Installation
Check if the installation is successful using pkg-config:
pkg-config --cflags --libs libmongoc-1.0
# Output similar to: -I/usr/local/include/libmongoc-1.0 -I/usr/local/include/bson-1.0 -lmongoc-1.0 -lbson-1.0
Core Process of Operating MongoDB in C Language
Connecting to MongoDB
Use mongoc_client_new() to establish a connection, specifying the MongoDB URI (e.g., mongodb://localhost:27017).
#include <mongoc/mongoc.h>
#include <bson/bson.h>
int main() {
mongoc_client_t *client = NULL;
mongoc_collection_t *collection = NULL;
bson_error_t error;
// 1. Initialize libmongoc (only once globally)
mongoc_init();
// 2. Create MongoDB client (connect to local port 27017)
client = mongoc_client_new("mongodb://localhost:27017/");
if (!client) {
fprintf(stderr, "Failed to create client\n");
return 1;
}
// 3. Get database (assuming database name is "test_db")
mongoc_database_t *db = mongoc_client_get_database(client, "test_db");
if (!db) {
fprintf(stderr, "Failed to get database\n");
goto cleanup;
}
// 4. Get collection (assuming collection name is "users")
collection = mongoc_database_get_collection(db, "users");
if (!collection) {
fprintf(stderr, "Failed to get collection\n");
goto cleanup;
}
// ... subsequent operations (CRUD)
cleanup:
// 5. Release resources (in reverse order)
if (collection) mongoc_collection_destroy(collection);
if (db) mongoc_database_destroy(db);
if (client) mongoc_client_destroy(client);
mongoc_cleanup();
return 0;
}
Core Operations: CRUD (Create, Read, Update, Delete)
Inserting Documents (Create)
Use mongoc_collection_insert_one() to insert a single document, requiring construction of a bson_t type document.
// Example of inserting a document
void insert_user(mongoc_collection_t *collection) {
bson_t *doc = bson_new(); // Create empty BSON document
bson_error_t error;
// Construct document fields (key-value pairs)
BSON_APPEND_UTF8(doc, "name", "Alice"); // String
BSON_APPEND_INT32(doc, "age", 30); // Integer
BSON_APPEND_BOOL(doc, "is_student", false); // Boolean
BSON_APPEND_DOUBLE(doc, "score", 92.5); // Double
BSON_APPEND_OID(doc, "_id", &oid); // Optional: explicitly specify _id (otherwise MongoDB auto-generates)
// Insert document into collection
bool ret = mongoc_collection_insert_one(
collection,
doc,
NULL, // Insert options (e.g., write concern, optional)
NULL, // Output result (optional)
&error // Error information
);
if (!ret) {
fprintf(stderr, "Insert failed: %s\n", error.message);
} else {
printf("Inserted document ID: %s\n", bson_oid_to_string(&oid));
}
bson_destroy(doc); // Destroy BSON document (free memory)
}
Querying Documents (Read)
Use mongoc_collection_find_with_opts() to query data, construct query conditions with bson_t, and iterate through the result set.
// Example of querying documents (query users with age >= 25)
void query_users(mongoc_collection_t *collection) {
bson_t *query = BCON_NEW(
"age", BCON_INT32, 25 // Condition: age >= 25 (BCON macro simplifies BSON construction)
);
mongoc_cursor_t *cursor = mongoc_collection_find_with_opts(
collection,
query,
NULL, // Query options (e.g., sort, pagination, optional)
NULL // Read preference (optional)
);
bson_error_t error;
// Iterate through result set
const bson_t *doc;
while (mongoc_cursor_next(cursor, &doc)) {
// Parse document fields
const char *name;
int age;
bool is_student;
if (bson_lookup_utf8(doc, "name", &name) &&
bson_lookup_int32(doc, "age", &age) &&
bson_lookup_bool(doc, "is_student", &is_student)) {
printf("Name: %s, Age: %d, Student: %s\n",
name, age, is_student ? "Yes" : "No");
}
}
// Check for errors during iteration
if (mongoc_cursor_error(cursor, &error)) {
fprintf(stderr, "Query failed: %s\n", error.message);
}
// Clean up resources
mongoc_cursor_destroy(cursor);
bson_destroy(query);
}
Updating Documents (Update)
Use mongoc_collection_update_one() to update a single document, supporting update operators such as $set, $inc.
// Example of updating a document (change Alice's age to 31)
void update_user(mongoc_collection_t *collection) {
bson_t *filter = BCON_NEW("name", BCON_UTF8, "Alice"); // Query condition
bson_t *update = BCON_NEW(
"$set", BCON_DOCUMENT(&(
BCON_NEW("age", BCON_INT32, 31) // Update operation: set age=31
))
);
bson_error_t error;
bool ret;
// Execute update (only update the first matching document)
ret = mongoc_collection_update_one(
collection,
filter,
update,
NULL, // Update options (e.g., upsert, optional)
NULL, // Output result (optional)
&error
);
if (!ret) {
fprintf(stderr, "Update failed: %s\n", error.message);
} else {
printf("Matched %d document(s), modified %d document(s)\n",
update->updated, update->modified_count); // Need to check output result
}
bson_destroy(filter);
bson_destroy(update);
}
Deleting Documents (Delete)
Use mongoc_collection_delete_one() to delete a single document, specifying the deletion condition with filter.
// Example of deleting a document (delete users with age >= 30)
void delete_user(mongoc_collection_t *collection) {
bson_t *filter = BCON_NEW("age", BCON_INT32, 30); // Query condition
bson_error_t error;
bool ret;
// Execute deletion (only delete the first matching document)
ret = mongoc_collection_delete_one(
collection,
filter,
NULL, // Delete options (optional)
NULL, // Output result (optional)
&error
);
if (!ret) {
fprintf(stderr, "Delete failed: %s\n", error.message);
} else {
printf("Deleted %d document(s)\n", delete->deleted_count); // Need to check output result
}
bson_destroy(filter);
}
Advanced Operations: Aggregation and Indexing
Aggregation Framework
MongoDB’s aggregation framework supports complex data processing (such as grouping, summing, filtering), implemented via mongoc_collection_aggregate().
// Aggregation example: count users by age
void aggregate_users(mongoc_collection_t *collection) {
// Construct aggregation pipeline ($group stage)
bson_t *pipeline = bson_new();
bson_t *stage_group = BCON_NEW(
"$group", BCON_DOCUMENT(&(
BCON_NEW("_id", BCON_INT32, "$age"), // Group by age
BCON_NEW("count", BCON_INT32, 0) // Count quantity
))
);
bson_array_append_document(pipeline, stage_group); // Add stage to pipeline
// Execute aggregation
mongoc_cursor_t *cursor = mongoc_collection_aggregate(
collection,
pipeline,
NULL, // Aggregation options (optional)
NULL // Read preference (optional)
);
bson_error_t error;
// Iterate through aggregation results
const bson_t *doc;
while (mongoc_cursor_next(cursor, &doc)) {
int age;
int count;
if (bson_lookup_int32(doc, "_id", &age) &&
bson_lookup_int32(doc, "count", &count)) {
printf("Age %d: %d users\n", age, count);
}
}
if (mongoc_cursor_error(cursor, &error)) {
fprintf(stderr, "Aggregation failed: %s\n", error.message);
}
// Clean up resources
mongoc_cursor_destroy(cursor);
bson_destroy(pipeline);
}
Creating Indexes
Create indexes for frequently queried fields to improve performance using mongoc_collection_create_index().
// Example of creating an index (create ascending index on age field)
void create_index(mongoc_collection_t *collection) {
bson_t *keys = BCON_NEW("age", BCON_INT32, 1); // 1 means ascending, -1 means descending
mongoc_index_opt_t opt = MONGOC_INDEX_OPT_INIT; // Index options (e.g., uniqueness)
bson_error_t error;
bson_t *index_name; // Store generated index name (optional)
// Create index (asynchronously in background)
bool ret = mongoc_collection_create_index(
collection,
keys,
&opt,
&index_name, // Output index name (e.g., "age_1")
&error
);
if (ret) {
printf("Index created: %s\n", bson_str(index_name));
bson_destroy(index_name);
} else {
fprintf(stderr, "Create index failed: %s\n", error.message);
}
bson_destroy(keys);
}
Compiling and Running
Compile Command
When compiling with gcc, link libmongoc and bson libraries via pkg-config:
gcc -o mongo_demo mongo_demo.c $(pkg-config --cflags --libs libmongoc-1.0)
Running the Test
Ensure the MongoDB service is started (default local port 27017), then execute the compiled program:
./mongo_demo
Notes
- Error Handling: All MongoDB C API operations may return errors (via
bson_error_t), and error information must always be checked. - Resource Release: Objects such as
bson_t,mongoc_cursor_t,mongoc_collection_tmust be manually released usingbson_destroy(),mongoc_cursor_destroy(), etc., to avoid memory leaks. - Thread Safety: The libmongoc client (
mongoc_client_t) is thread-safe, but collections (mongoc_collection_t) and cursors (mongoc_cursor_t) are not; avoid sharing across threads. - Production Environment Configuration:
- Connection URI can include authentication (e.g.,
mongodb://user:pass@host:port/db). - Configure write concern and read preference to improve data reliability.
- Use connection pooling (
mongoc_client_pool_t) to manage client instances and optimize performance in high-concurrency scenarios.
- Connection URI can include authentication (e.g.,
Summary
Through the libmongoc driver, C language can efficiently interact with MongoDB, implementing complete CRUD operations and advanced features (such as aggregation and indexing). The key steps include:
- Install libmongoc and initialize;
- Establish connection and get collection;
- Use BSON to construct query/update conditions;
- Call API to execute operations and handle results;
- Strictly release resources and handle errors.
In actual development, refer to the MongoDB C Driver official documentation for more details and advanced usage.



