Adding Data#

The previous tutorial covered how to create and destroy document objects, but we’ll eventually want to insert content. This page will discuss how to insert data into a document object.

Getting a Mutator#

Modifying a bson_doc can’t be done directly. We need to obtain a bson_mut mutator for a document using bson_mutate():

#include <bson/mut.h>

void mutate_a_doc() {
    bson_doc doc = bson_new();

    // Begin mutation
    bson_mut mut = bson_mutate(&doc);
    (void)mut;

    bson_delete(doc);
}

Important

A bson_mut object retains a pointer to the bson_doc from which it was created. The origin bson_doc must remain in place while the bson_mut object is being used!

The bson_mut object does not need to be destroyed or finalized. Mutations performed are applied to the original bson_doc immediately as they execute.

Inserting Values#

Values can be inserted into a mutator using the bson_insert() generic function type:

void insert_something() {
    bson_doc doc = bson_new();
    bson_mut m   = bson_mutate(&doc);
    /* Content:
        {}
    */
    bson_insert(&m, "foo", "bar");
    /* Content:
        {
            "foo": "bar"
        }
    */
    bson_delete(doc);
}

The bson_insert() function supports multiple signatures. The element type will be inferred from the final argument, which is the value to insert. Refer to its documentation page for full details.

Inserting in Other Positions#

Values can be inserted into the middle or front of a document, and the existing elements will be rearranged appropriately. This is done by passing an iterator to bson_insert() as the second argument:

void prepend_something() {
    bson_doc doc = bson_new();
    bson_mut m   = bson_mutate(&doc);
    /* Content:
        {}
    */
    bson_insert(&m, bson_begin(doc), "foo", "bar");
    /* Content:
        {
            "foo": "bar"
        }
    */
    bson_insert(&m, bson_begin(doc), "baz", "quux");
    /* Content:
        {
            "baz": "quux",
            "foo": "bar"
        }
    */
    bson_delete(doc);
}

When no position is given to bson_insert(), it will implicitly insert the element at the end.

Working with iterators will be covered in the next page.

Inserting in a Child Document#

bson_mut supports consrtucting a heirarchy of document objects. After inserting a new document, the returned iterator can be used to obtained a bson_mut that manipulates a child document:

void subdoc_modify() {
    bson_doc      doc     = bson_new();
    bson_mut      top_mut = bson_mutate(&doc);
    bson_iterator it      = bson_insert(&top_mut, "child", bson_view_null);
    /* Content:
        {
            "child": {}
        }
    */
    bson_mut child_mut = bson_mut_child(&top_mut, it);
    bson_insert(&child_mut, "foo", "Within a child document");
    /* Content:
        {
            "child": {
                "foo": "Within a child document"
            }
        }
    */
    bson_delete(doc);
}

Note

The iterator that refers to the child document will be invalidated when the child document is modified. To recover a valid iterator, use bson_mut_parent_iterator().