Skip to content

Commit f974c49

Browse files
authored
CDRIVER-4612 document management of search indexes (mongodb#1366)
* add index-management tests From PR mongodb/specifications#1442 * add test search operations and implement without helpers * document management of search indexes
1 parent d08a50f commit f974c49

13 files changed

+1191
-2
lines changed

src/libmongoc/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,7 @@ if (ENABLE_EXAMPLES)
10951095
mongoc_add_example (example-command-monitoring ${PROJECT_SOURCE_DIR}/examples/example-command-monitoring.c)
10961096
mongoc_add_example (example-command-with-opts ${PROJECT_SOURCE_DIR}/examples/example-command-with-opts.c)
10971097
mongoc_add_example (example-manage-collection-indexes ${PROJECT_SOURCE_DIR}/examples/example-manage-collection-indexes.c)
1098+
mongoc_add_example (example-manage-search-indexes ${PROJECT_SOURCE_DIR}/examples/example-manage-search-indexes.c)
10981099
mongoc_add_example (example-gridfs ${PROJECT_SOURCE_DIR}/examples/example-gridfs.c)
10991100
mongoc_add_example (example-gridfs-bucket ${PROJECT_SOURCE_DIR}/examples/example-gridfs-bucket.c)
11001101
if (NOT WIN32 AND ENABLE_EXAMPLES)

src/libmongoc/doc/manage-collection-indexes.rst

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,40 @@ To drop an index, use :symbol:`mongoc_collection_drop_index_with_opts`. The inde
2828
:dedent: 6
2929

3030
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>`_.
31+
32+
Manage Atlas Search Indexes
33+
---------------------------
34+
35+
To create an Atlas Search Index, use the ``createSearchIndexes`` command:
36+
37+
.. literalinclude:: ../examples/example-manage-search-indexes.c
38+
:language: c
39+
:start-after: // Create an Atlas Search Index ... begin
40+
:end-before: // Create an Atlas Search Index ... end
41+
:dedent: 6
42+
43+
To list Atlas Search Indexes, use the ``$listSearchIndexes`` aggregation stage:
44+
45+
.. literalinclude:: ../examples/example-manage-search-indexes.c
46+
:language: c
47+
:start-after: // List Atlas Search Indexes ... begin
48+
:end-before: // List Atlas Search Indexes ... end
49+
:dedent: 6
50+
51+
To update an Atlas Search Index, use the ``updateSearchIndex`` command:
52+
53+
.. literalinclude:: ../examples/example-manage-search-indexes.c
54+
:language: c
55+
:start-after: // Update an Atlas Search Index ... begin
56+
:end-before: // Update an Atlas Search Index ... end
57+
:dedent: 6
58+
59+
To drop an Atlas Search Index, use the ``dropSearchIndex`` command:
60+
61+
.. literalinclude:: ../examples/example-manage-search-indexes.c
62+
:language: c
63+
:start-after: // Drop an Atlas Search Index ... begin
64+
:end-before: // Drop an Atlas Search Index ... end
65+
:dedent: 6
66+
67+
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>`_.
Lines changed: 230 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
// example-manage-search-indexes creates, lists, updates, and deletes an Atlas
2+
// search index from the `test.test` collection.
3+
// Example is expected to be run against a MongoDB Atlas cluster.
4+
5+
#include <mongoc/mongoc.h>
6+
#include <stdlib.h> // abort
7+
8+
#define HANDLE_ERROR(...) \
9+
if (1) { \
10+
fprintf (stderr, __VA_ARGS__); \
11+
fprintf (stderr, "\n"); \
12+
goto fail; \
13+
} else \
14+
(void) 0
15+
16+
#define ASSERT(stmt) \
17+
if (!stmt) { \
18+
fprintf (stderr, \
19+
"assertion failed on line: %d, statement: %s\n", \
20+
__LINE__, \
21+
#stmt); \
22+
abort (); \
23+
} else \
24+
(void) 0
25+
26+
int
27+
main (int argc, char *argv[])
28+
{
29+
mongoc_client_t *client = NULL;
30+
const char *uri_string =
31+
"mongodb://127.0.0.1/?appname=create-search-indexes-example";
32+
mongoc_uri_t *uri = NULL;
33+
mongoc_collection_t *coll = NULL;
34+
bson_error_t error;
35+
bool ok = false;
36+
37+
mongoc_init ();
38+
39+
if (argc > 2) {
40+
HANDLE_ERROR (
41+
"Unexpected arguments. Expected usage: %s [CONNECTION_STRING]",
42+
argv[0]);
43+
}
44+
45+
if (argc > 1) {
46+
uri_string = argv[1];
47+
}
48+
49+
uri = mongoc_uri_new_with_error (uri_string, &error);
50+
if (!uri) {
51+
HANDLE_ERROR ("Failed to parse URI: %s", error.message);
52+
}
53+
client = mongoc_client_new_from_uri_with_error (uri, &error);
54+
if (!client) {
55+
HANDLE_ERROR ("Failed to create client: %s", error.message);
56+
}
57+
58+
// Create a random collection name.
59+
char collname[25];
60+
{
61+
// There is a server-side limitation that prevents multiple search indexes
62+
// from being created with the same name, definition and collection name.
63+
// Atlas search index management operations are asynchronous. Dropping a
64+
// collection may not result in the index being dropped immediately. Use a
65+
// randomly generated collection name to avoid errors.
66+
bson_oid_t oid;
67+
bson_oid_init (&oid, NULL);
68+
bson_oid_to_string (&oid, collname);
69+
}
70+
71+
// Create collection object.
72+
{
73+
// Create the collection server-side to avoid the server error:
74+
// "Collection 'test.<collname>' does not exist."
75+
mongoc_database_t *db = mongoc_client_get_database (client, "test");
76+
coll = mongoc_database_create_collection (
77+
db, collname, NULL /* options */, &error);
78+
if (!coll) {
79+
mongoc_database_destroy (db);
80+
HANDLE_ERROR ("Failed to create collection: %s", error.message);
81+
}
82+
mongoc_database_destroy (db);
83+
}
84+
85+
// Check that $listSearchIndexes pipeline stage is supported.
86+
// This is intended to check that a MongoDB Atlas cluster is used.
87+
{
88+
const char *pipeline_str =
89+
BSON_STR ({"pipeline" : [ {"$listSearchIndexes" : {}} ]});
90+
bson_t pipeline;
91+
ASSERT (bson_init_from_json (&pipeline, pipeline_str, -1, &error));
92+
mongoc_cursor_t *cursor =
93+
mongoc_collection_aggregate (coll,
94+
MONGOC_QUERY_NONE,
95+
&pipeline,
96+
NULL /* opts */,
97+
NULL /* read_prefs */);
98+
const bson_t *got;
99+
while (mongoc_cursor_next (cursor, &got))
100+
;
101+
if (mongoc_cursor_error (cursor, &error)) {
102+
bson_destroy (&pipeline);
103+
mongoc_cursor_destroy (cursor);
104+
HANDLE_ERROR ("Failed to run $listSearchIndexes with error: %s\n"
105+
"Does the URI point to a MongoDB Atlas cluster? %s",
106+
error.message,
107+
uri_string);
108+
}
109+
bson_destroy (&pipeline);
110+
mongoc_cursor_destroy (cursor);
111+
}
112+
113+
{
114+
// Create an Atlas Search Index ... begin
115+
bson_t cmd;
116+
// Create command.
117+
{
118+
char *cmd_str = bson_strdup_printf (
119+
BSON_STR ({
120+
"createSearchIndexes" : "%s",
121+
"indexes" : [ {
122+
"definition" : {"mappings" : {"dynamic" : false}},
123+
"name" : "test-index"
124+
} ]
125+
}),
126+
collname);
127+
ASSERT (bson_init_from_json (&cmd, cmd_str, -1, &error));
128+
bson_free (cmd_str);
129+
}
130+
if (!mongoc_collection_command_simple (
131+
coll, &cmd, NULL /* read_prefs */, NULL /* reply */, &error)) {
132+
bson_destroy (&cmd);
133+
HANDLE_ERROR ("Failed to run createSearchIndexes: %s", error.message);
134+
}
135+
printf ("Created index: \"test-index\"\n");
136+
bson_destroy (&cmd);
137+
// Create an Atlas Search Index ... end
138+
}
139+
140+
{
141+
// List Atlas Search Indexes ... begin
142+
const char *pipeline_str =
143+
BSON_STR ({"pipeline" : [ {"$listSearchIndexes" : {}} ]});
144+
bson_t pipeline;
145+
ASSERT (bson_init_from_json (&pipeline, pipeline_str, -1, &error));
146+
mongoc_cursor_t *cursor =
147+
mongoc_collection_aggregate (coll,
148+
MONGOC_QUERY_NONE,
149+
&pipeline,
150+
NULL /* opts */,
151+
NULL /* read_prefs */);
152+
printf ("Listing indexes:\n");
153+
const bson_t *got;
154+
while (mongoc_cursor_next (cursor, &got)) {
155+
char *got_str = bson_as_canonical_extended_json (got, NULL);
156+
printf (" %s\n", got_str);
157+
bson_free (got_str);
158+
}
159+
if (mongoc_cursor_error (cursor, &error)) {
160+
bson_destroy (&pipeline);
161+
mongoc_cursor_destroy (cursor);
162+
HANDLE_ERROR ("Failed to run $listSearchIndexes: %s", error.message);
163+
}
164+
bson_destroy (&pipeline);
165+
mongoc_cursor_destroy (cursor);
166+
// List Atlas Search Indexes ... end
167+
}
168+
169+
{
170+
// Update an Atlas Search Index ... begin
171+
bson_t cmd;
172+
// Create command.
173+
{
174+
char *cmd_str = bson_strdup_printf (
175+
BSON_STR ({
176+
"updateSearchIndex" : "%s",
177+
"definition" : {"mappings" : {"dynamic" : true}},
178+
"name" : "test-index"
179+
}),
180+
collname);
181+
ASSERT (bson_init_from_json (&cmd, cmd_str, -1, &error));
182+
bson_free (cmd_str);
183+
}
184+
if (!mongoc_collection_command_simple (
185+
coll, &cmd, NULL /* read_prefs */, NULL /* reply */, &error)) {
186+
bson_destroy (&cmd);
187+
HANDLE_ERROR ("Failed to run updateSearchIndex: %s", error.message);
188+
}
189+
printf ("Updated index: \"test-index\"\n");
190+
bson_destroy (&cmd);
191+
// Update an Atlas Search Index ... end
192+
}
193+
194+
{
195+
// Drop an Atlas Search Index ... begin
196+
bson_t cmd;
197+
// Create command.
198+
{
199+
char *cmd_str = bson_strdup_printf (
200+
BSON_STR ({"dropSearchIndex" : "%s", "name" : "test-index"}),
201+
collname);
202+
ASSERT (bson_init_from_json (&cmd, cmd_str, -1, &error));
203+
bson_free (cmd_str);
204+
}
205+
if (!mongoc_collection_command_simple (
206+
coll, &cmd, NULL /* read_prefs */, NULL /* reply */, &error)) {
207+
bson_destroy (&cmd);
208+
HANDLE_ERROR ("Failed to run dropSearchIndex: %s", error.message);
209+
}
210+
printf ("Dropped index: \"test-index\"\n");
211+
bson_destroy (&cmd);
212+
// Drop an Atlas Search Index ... end
213+
}
214+
215+
// Drop created collection.
216+
{
217+
if (!mongoc_collection_drop (coll, &error)) {
218+
HANDLE_ERROR (
219+
"Failed to drop collection '%s': %s", collname, error.message);
220+
}
221+
}
222+
223+
ok = true;
224+
fail:
225+
mongoc_collection_destroy (coll);
226+
mongoc_client_destroy (client);
227+
mongoc_uri_destroy (uri);
228+
mongoc_cleanup ();
229+
return ok ? EXIT_SUCCESS : EXIT_FAILURE;
230+
}

src/libmongoc/tests/bsonutil/bson-match.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,9 @@ bson_matcher_match (bson_matcher_t *matcher,
565565

566566
memcpy (&tmp_error, error, sizeof (bson_error_t));
567567
test_set_error (error,
568-
"BSON match failed: %s\nExpected: %s\nActual: %s",
568+
"BSON match failed: %s\n"
569+
"Expected: %s\n"
570+
"Actual: %s",
569571
tmp_error.message,
570572
bson_val_to_json (expected),
571573
bson_val_to_json (actual));

src/libmongoc/tests/bsonutil/bson-parser.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,7 @@ bson_parser_parse (bson_parser_t *parser, bson_t *in, bson_error_t *error)
708708
{
709709
if (!entry->optional && !entry->set) {
710710
test_set_error (error,
711-
"Required field %s was not found parsing: %s",
711+
"Required field '%s' was not found parsing: %s",
712712
entry->key,
713713
tmp_json (in));
714714
return false;

0 commit comments

Comments
 (0)