Skip to content

Commit

Permalink
CDRIVER-4612 document management of search indexes (#1366)
Browse files Browse the repository at this point in the history
* add index-management tests

From PR mongodb/specifications#1442

* add test search operations and implement without helpers

* document management of search indexes
  • Loading branch information
kevinAlbs authored Aug 1, 2023
1 parent d08a50f commit f974c49
Show file tree
Hide file tree
Showing 13 changed files with 1,191 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/libmongoc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1095,6 +1095,7 @@ if (ENABLE_EXAMPLES)
mongoc_add_example (example-command-monitoring ${PROJECT_SOURCE_DIR}/examples/example-command-monitoring.c)
mongoc_add_example (example-command-with-opts ${PROJECT_SOURCE_DIR}/examples/example-command-with-opts.c)
mongoc_add_example (example-manage-collection-indexes ${PROJECT_SOURCE_DIR}/examples/example-manage-collection-indexes.c)
mongoc_add_example (example-manage-search-indexes ${PROJECT_SOURCE_DIR}/examples/example-manage-search-indexes.c)
mongoc_add_example (example-gridfs ${PROJECT_SOURCE_DIR}/examples/example-gridfs.c)
mongoc_add_example (example-gridfs-bucket ${PROJECT_SOURCE_DIR}/examples/example-gridfs-bucket.c)
if (NOT WIN32 AND ENABLE_EXAMPLES)
Expand Down
37 changes: 37 additions & 0 deletions src/libmongoc/doc/manage-collection-indexes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,40 @@ To drop an index, use :symbol:`mongoc_collection_drop_index_with_opts`. The inde
:dedent: 6

For a full example, see `example-manage-collection-indexes.c <https://github.com/mongodb/mongo-c-driver/blob/master/src/libmongoc/examples/example-manage-collection-indexes.c>`_.

Manage Atlas Search Indexes
---------------------------

To create an Atlas Search Index, use the ``createSearchIndexes`` command:

.. literalinclude:: ../examples/example-manage-search-indexes.c
:language: c
:start-after: // Create an Atlas Search Index ... begin
:end-before: // Create an Atlas Search Index ... end
:dedent: 6

To list Atlas Search Indexes, use the ``$listSearchIndexes`` aggregation stage:

.. literalinclude:: ../examples/example-manage-search-indexes.c
:language: c
:start-after: // List Atlas Search Indexes ... begin
:end-before: // List Atlas Search Indexes ... end
:dedent: 6

To update an Atlas Search Index, use the ``updateSearchIndex`` command:

.. literalinclude:: ../examples/example-manage-search-indexes.c
:language: c
:start-after: // Update an Atlas Search Index ... begin
:end-before: // Update an Atlas Search Index ... end
:dedent: 6

To drop an Atlas Search Index, use the ``dropSearchIndex`` command:

.. literalinclude:: ../examples/example-manage-search-indexes.c
:language: c
:start-after: // Drop an Atlas Search Index ... begin
:end-before: // Drop an Atlas Search Index ... end
:dedent: 6

For a full example, see `example-manage-search-indexes.c <https://github.com/mongodb/mongo-c-driver/blob/master/src/libmongoc/examples/example-manage-search-indexes.c>`_.
230 changes: 230 additions & 0 deletions src/libmongoc/examples/example-manage-search-indexes.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
// example-manage-search-indexes creates, lists, updates, and deletes an Atlas
// search index from the `test.test` collection.
// Example is expected to be run against a MongoDB Atlas cluster.

#include <mongoc/mongoc.h>
#include <stdlib.h> // abort

#define HANDLE_ERROR(...) \
if (1) { \
fprintf (stderr, __VA_ARGS__); \
fprintf (stderr, "\n"); \
goto fail; \
} else \
(void) 0

#define ASSERT(stmt) \
if (!stmt) { \
fprintf (stderr, \
"assertion failed on line: %d, statement: %s\n", \
__LINE__, \
#stmt); \
abort (); \
} else \
(void) 0

int
main (int argc, char *argv[])
{
mongoc_client_t *client = NULL;
const char *uri_string =
"mongodb://127.0.0.1/?appname=create-search-indexes-example";
mongoc_uri_t *uri = NULL;
mongoc_collection_t *coll = NULL;
bson_error_t error;
bool ok = false;

mongoc_init ();

if (argc > 2) {
HANDLE_ERROR (
"Unexpected arguments. Expected usage: %s [CONNECTION_STRING]",
argv[0]);
}

if (argc > 1) {
uri_string = argv[1];
}

uri = mongoc_uri_new_with_error (uri_string, &error);
if (!uri) {
HANDLE_ERROR ("Failed to parse URI: %s", error.message);
}
client = mongoc_client_new_from_uri_with_error (uri, &error);
if (!client) {
HANDLE_ERROR ("Failed to create client: %s", error.message);
}

// Create a random collection name.
char collname[25];
{
// There is a server-side limitation that prevents multiple search indexes
// from being created with the same name, definition and collection name.
// Atlas search index management operations are asynchronous. Dropping a
// collection may not result in the index being dropped immediately. Use a
// randomly generated collection name to avoid errors.
bson_oid_t oid;
bson_oid_init (&oid, NULL);
bson_oid_to_string (&oid, collname);
}

// Create collection object.
{
// Create the collection server-side to avoid the server error:
// "Collection 'test.<collname>' does not exist."
mongoc_database_t *db = mongoc_client_get_database (client, "test");
coll = mongoc_database_create_collection (
db, collname, NULL /* options */, &error);
if (!coll) {
mongoc_database_destroy (db);
HANDLE_ERROR ("Failed to create collection: %s", error.message);
}
mongoc_database_destroy (db);
}

// Check that $listSearchIndexes pipeline stage is supported.
// This is intended to check that a MongoDB Atlas cluster is used.
{
const char *pipeline_str =
BSON_STR ({"pipeline" : [ {"$listSearchIndexes" : {}} ]});
bson_t pipeline;
ASSERT (bson_init_from_json (&pipeline, pipeline_str, -1, &error));
mongoc_cursor_t *cursor =
mongoc_collection_aggregate (coll,
MONGOC_QUERY_NONE,
&pipeline,
NULL /* opts */,
NULL /* read_prefs */);
const bson_t *got;
while (mongoc_cursor_next (cursor, &got))
;
if (mongoc_cursor_error (cursor, &error)) {
bson_destroy (&pipeline);
mongoc_cursor_destroy (cursor);
HANDLE_ERROR ("Failed to run $listSearchIndexes with error: %s\n"
"Does the URI point to a MongoDB Atlas cluster? %s",
error.message,
uri_string);
}
bson_destroy (&pipeline);
mongoc_cursor_destroy (cursor);
}

{
// Create an Atlas Search Index ... begin
bson_t cmd;
// Create command.
{
char *cmd_str = bson_strdup_printf (
BSON_STR ({
"createSearchIndexes" : "%s",
"indexes" : [ {
"definition" : {"mappings" : {"dynamic" : false}},
"name" : "test-index"
} ]
}),
collname);
ASSERT (bson_init_from_json (&cmd, cmd_str, -1, &error));
bson_free (cmd_str);
}
if (!mongoc_collection_command_simple (
coll, &cmd, NULL /* read_prefs */, NULL /* reply */, &error)) {
bson_destroy (&cmd);
HANDLE_ERROR ("Failed to run createSearchIndexes: %s", error.message);
}
printf ("Created index: \"test-index\"\n");
bson_destroy (&cmd);
// Create an Atlas Search Index ... end
}

{
// List Atlas Search Indexes ... begin
const char *pipeline_str =
BSON_STR ({"pipeline" : [ {"$listSearchIndexes" : {}} ]});
bson_t pipeline;
ASSERT (bson_init_from_json (&pipeline, pipeline_str, -1, &error));
mongoc_cursor_t *cursor =
mongoc_collection_aggregate (coll,
MONGOC_QUERY_NONE,
&pipeline,
NULL /* opts */,
NULL /* read_prefs */);
printf ("Listing indexes:\n");
const bson_t *got;
while (mongoc_cursor_next (cursor, &got)) {
char *got_str = bson_as_canonical_extended_json (got, NULL);
printf (" %s\n", got_str);
bson_free (got_str);
}
if (mongoc_cursor_error (cursor, &error)) {
bson_destroy (&pipeline);
mongoc_cursor_destroy (cursor);
HANDLE_ERROR ("Failed to run $listSearchIndexes: %s", error.message);
}
bson_destroy (&pipeline);
mongoc_cursor_destroy (cursor);
// List Atlas Search Indexes ... end
}

{
// Update an Atlas Search Index ... begin
bson_t cmd;
// Create command.
{
char *cmd_str = bson_strdup_printf (
BSON_STR ({
"updateSearchIndex" : "%s",
"definition" : {"mappings" : {"dynamic" : true}},
"name" : "test-index"
}),
collname);
ASSERT (bson_init_from_json (&cmd, cmd_str, -1, &error));
bson_free (cmd_str);
}
if (!mongoc_collection_command_simple (
coll, &cmd, NULL /* read_prefs */, NULL /* reply */, &error)) {
bson_destroy (&cmd);
HANDLE_ERROR ("Failed to run updateSearchIndex: %s", error.message);
}
printf ("Updated index: \"test-index\"\n");
bson_destroy (&cmd);
// Update an Atlas Search Index ... end
}

{
// Drop an Atlas Search Index ... begin
bson_t cmd;
// Create command.
{
char *cmd_str = bson_strdup_printf (
BSON_STR ({"dropSearchIndex" : "%s", "name" : "test-index"}),
collname);
ASSERT (bson_init_from_json (&cmd, cmd_str, -1, &error));
bson_free (cmd_str);
}
if (!mongoc_collection_command_simple (
coll, &cmd, NULL /* read_prefs */, NULL /* reply */, &error)) {
bson_destroy (&cmd);
HANDLE_ERROR ("Failed to run dropSearchIndex: %s", error.message);
}
printf ("Dropped index: \"test-index\"\n");
bson_destroy (&cmd);
// Drop an Atlas Search Index ... end
}

// Drop created collection.
{
if (!mongoc_collection_drop (coll, &error)) {
HANDLE_ERROR (
"Failed to drop collection '%s': %s", collname, error.message);
}
}

ok = true;
fail:
mongoc_collection_destroy (coll);
mongoc_client_destroy (client);
mongoc_uri_destroy (uri);
mongoc_cleanup ();
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
4 changes: 3 additions & 1 deletion src/libmongoc/tests/bsonutil/bson-match.c
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,9 @@ bson_matcher_match (bson_matcher_t *matcher,

memcpy (&tmp_error, error, sizeof (bson_error_t));
test_set_error (error,
"BSON match failed: %s\nExpected: %s\nActual: %s",
"BSON match failed: %s\n"
"Expected: %s\n"
"Actual: %s",
tmp_error.message,
bson_val_to_json (expected),
bson_val_to_json (actual));
Expand Down
2 changes: 1 addition & 1 deletion src/libmongoc/tests/bsonutil/bson-parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ bson_parser_parse (bson_parser_t *parser, bson_t *in, bson_error_t *error)
{
if (!entry->optional && !entry->set) {
test_set_error (error,
"Required field %s was not found parsing: %s",
"Required field '%s' was not found parsing: %s",
entry->key,
tmp_json (in));
return false;
Expand Down
Loading

0 comments on commit f974c49

Please sign in to comment.