Search code examples
mongodbmongo-c-driver

How to insert document with empty key using Mongo C driver?


I have this program in C (a slight variation of the hello world example at Mongo C driver documentation:

#include <bson/bson.h>
#include <mongoc/mongoc.h>
#include <stdio.h>

// file insert.c
// compiled with: gcc -o insert insert.c $(pkg-config --libs --cflags libmongoc-1.0)

int main (int   argc, char *argv[])
{
    mongoc_client_t *client;
    mongoc_collection_t *collection;
    bson_error_t error;
    bson_oid_t oid;
    bson_t *doc;

    mongoc_init ();

    client = mongoc_client_new ("mongodb://localhost:27017/?appname=insert-example");
    collection = mongoc_client_get_collection (client, "mydb", "mycoll");

    doc = bson_new ();
    bson_oid_init (&oid, NULL);
    BSON_APPEND_OID (doc, "_id", &oid);
    BSON_APPEND_UTF8 (doc, "", "my_key_is_empty");

    if (!mongoc_collection_insert_one (
        collection, doc, NULL, NULL, &error)) {
    fprintf (stderr, "%s\n", error.message);
    }

    bson_destroy (doc);
    mongoc_collection_destroy (collection);
    mongoc_client_destroy (client);
    mongoc_cleanup ();

    return 0;
}

The important statement is this one, to set an empty BSON key (which is a bit weird but legal):

BSON_APPEND_UTF8 (doc, "", "my_key_is_empty");

If I run the program I get this error:

invalid document for insert: empty key

It's a bit surprising because if I try to do the same with the Mongo shell, it works fine:

> db.mycoll.insert({"": "my_key_is_empty"})
WriteResult({ "nInserted" : 1 })
> db.mycoll.find()
{ "_id" : ObjectId("60182cb49fb197394497431e"), "" : "my_key_is_empty" }

So:

  1. This is a limitation in the C driver, or
  2. I'm doing something wrong :)

Could you help me with this, please? Thanks!

Some additional info about my system:

  • gcc version: 6.3.0
  • Mongo C driver version: 1.16.0
  • MongoDB version: 4.4.1
  • Operating system: Debian 9.3

Solution

  • This version of the program solves the issue:

    include <bson/bson.h>
    #include <mongoc/mongoc.h>
    #include <stdio.h>
    
    // file insert.c
    // compiled with: gcc -o insert insert.c $(pkg-config --libs --cflags libmongoc-1.0)
    
    int main (int   argc, char *argv[])
    {
        mongoc_client_t *client;
        mongoc_collection_t *collection;
        bson_error_t error;
        bson_oid_t oid;
        bson_t *doc;
    
        mongoc_init ();
    
        client = mongoc_client_new ("mongodb://localhost:27017/?appname=insert-example");
        collection = mongoc_client_get_collection (client, "mydb", "mycoll");
    
        doc = bson_new ();
        bson_oid_init (&oid, NULL);
        BSON_APPEND_OID (doc, "_id", &oid);
        BSON_APPEND_UTF8 (doc, "", "my_key_is_empty");
    
        bson_t *opt = BCON_NEW("validate", BCON_BOOL(false));
        if (!mongoc_collection_insert_one (
            collection, doc, opt, NULL, &error)) {
        fprintf (stderr, "%s\n", error.message);
        }
    
        bson_destroy (doc);
        bson_destroy (opt);
        mongoc_collection_destroy (collection);
        mongoc_client_destroy (client);
        mongoc_cleanup ();
    
        return 0;
    }
    

    The important part is this one, to turn off validation:

        bson_t *opt = BCON_NEW("validate", BCON_BOOL(false));
        if (!mongoc_collection_insert_one (
            collection, doc, opt, NULL, &error)) {
        ...
        }
    
        ...
        bson_destroy (opt);