- stretch 1.4.2-1
| BASIC_AGGREGATION_EXAMPLES(3) | Library Functions Manual | BASIC_AGGREGATION_EXAMPLES(3) |
NAME¶
Basic_Aggregation_Examples - NoneSETUP¶
First we'll write some code to insert sample data:/* Don't try to compile this file on it's own. It's meant to be #included
by example code */
/* Insert some sample data */
bool insert_data (mongoc_collection_t* collection)
{
mongoc_bulk_operation_t *bulk;
enum N { ndocs = 4 };
bson_t* docs[ndocs];
bson_error_t error;
int i = 0;
bool ret;
bulk = mongoc_collection_create_bulk_operation (collection, true, NULL);
docs[0] = BCON_NEW ("x", BCON_DOUBLE (1.0), "tags", "[", "dog", "cat", "]");
docs[1] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags", "[", "cat", "]");
docs[2] = BCON_NEW ("x", BCON_DOUBLE (2.0), "tags",
"[", "mouse", "cat", "dog", "]");
docs[3] = BCON_NEW ("x", BCON_DOUBLE (3.0), "tags", "[", "]");
for (i = 0; i < ndocs; i++) {
mongoc_bulk_operation_insert (bulk, docs[i]);
bson_destroy (docs[i]);
docs[i] = NULL;
}
ret = mongoc_bulk_operation_execute (bulk, NULL, &error);
if (!ret) {
fprintf (stderr, "Error inserting data: %s\n", error.message);
}
mongoc_bulk_operation_destroy (bulk);
return ret;
}
/* A helper which we'll use a lot later on */
void print_res (const bson_t* reply)
{
BSON_ASSERT (reply);
char *str = bson_as_json (reply, NULL);
printf ("%s\n", str);
bson_free (str);
}
DISTINCT COMMAND¶
This is how to use the distinct command to get the distinct values of x which are greater than 1 :bool distinct (mongoc_database_t* database)
{
bson_t* command;
bson_t reply;
bson_error_t error;
bool res;
bson_iter_t iter;
bson_iter_t array_iter;
double val;
command = BCON_NEW ("distinct", BCON_UTF8 (COLLECTION_NAME),
"key", BCON_UTF8 ("x"),
"query", "{",
"x", "{", "$gt", BCON_DOUBLE (1.0), "}",
"}"
);
res = mongoc_database_command_simple (database, command, NULL,
&reply, &error);
if (!res) {
fprintf (stderr, "Error with distinct: %s\n", error.message);
goto cleanup;
}
/* Do something with reply (in this case iterate through the values) */
if (!(bson_iter_init_find (&iter, &reply, "values") &&
BSON_ITER_HOLDS_ARRAY (&iter) &&
bson_iter_recurse (&iter, &array_iter))) {
fprintf (stderr, "Couldn't extract \"values\" field from response\n");
goto cleanup;
}
while (bson_iter_next (&array_iter)) {
if (BSON_ITER_HOLDS_DOUBLE (&array_iter)) {
val = bson_iter_double (&array_iter);
printf ("Next double: %f\n", val);
}
}
cleanup:
/* cleanup */
bson_destroy (command);
bson_destroy (&reply);
return res;
}
MAPREDUCE - BASIC EXAMPLE¶
A simple example using the map reduce framework. It simply adds up the number of occurrences of each "tag".First define the map and reduce functions:
const char* const COLLECTION_NAME = "things";
/* Our map function just emits a single (key, 1) pair for each tag
in the array: */
const char* const MAPPER =
"function () {"
"this.tags.forEach(function(z) {"
"emit(z, 1);"
"});"
"}";
/* The reduce function sums over all of the emitted values for a
given key: */
const char* const REDUCER =
"function (key, values) {"
"var total = 0;"
"for (var i = 0; i < values.length; i++) {"
"total += values[i];"
"}"
"return total;"
"}";
/* Note We can’t just return values.length as the reduce function
might be called iteratively on the results of other reduce
steps. */
Run the mapReduce command:
bool map_reduce_basic (mongoc_database_t* database)
{
bson_t reply;
bson_t* command;
bool res;
bson_error_t error;
mongoc_cursor_t* cursor;
const bson_t* doc;
bool map_reduce_done = false;
bool query_done = false;
const char* out_collection_name = "outCollection";
mongoc_collection_t* out_collection;
/* Empty find query */
bson_t find_query = BSON_INITIALIZER;
/* Construct the mapReduce command */
/* Other arguments can also be specified here, like "query" or
"limit" and so on */
command = BCON_NEW ("mapReduce", BCON_UTF8 (COLLECTION_NAME),
"map", BCON_CODE (MAPPER),
"reduce", BCON_CODE (REDUCER),
"out", BCON_UTF8 (out_collection_name));
res = mongoc_database_command_simple (database, command, NULL,
&reply, &error);
map_reduce_done = true;
if (!res) {
fprintf (stderr, "MapReduce failed: %s\n", error.message);
goto cleanup;
}
/* Do something with the reply (it doesn't contain the mapReduce results) */
print_res (&reply);
/* Now we'll query outCollection to see what the results are */
out_collection = mongoc_database_get_collection (database,
out_collection_name);
cursor = mongoc_collection_find (out_collection, MONGOC_QUERY_NONE, 0, 0, 0,
&find_query, NULL, NULL);
query_done = true;
/* Do something with the results */
while (mongoc_cursor_next (cursor, &doc)) {
print_res (doc);
}
if (mongoc_cursor_error (cursor, &error)) {
fprintf (stderr, "ERROR: %s\n", error.message);
res = false;
goto cleanup;
}
cleanup:
/* cleanup */
if (query_done) {
mongoc_cursor_destroy (cursor);
mongoc_collection_destroy (out_collection);
}
if (map_reduce_done) {
bson_destroy (&reply);
bson_destroy (command);
}
return res;
}
MAPREDUCE - MORE COMPLICATED EXAMPLE¶
You must have replica set running for this.In this example we contact a secondary in the replica set and do an "inline" map reduce, so the results are returned immediately:
bool map_reduce_advanced (mongoc_database_t* database)
{
bson_t* command;
bson_error_t error;
bool res = true;
mongoc_cursor_t* cursor;
mongoc_read_prefs_t* read_pref;
const bson_t* doc;
/* Construct the mapReduce command */
/* Other arguments can also be specified here, like "query" or "limit"
and so on */
/* Read the results inline from a secondary replica */
command = BCON_NEW ("mapReduce", BCON_UTF8 (COLLECTION_NAME),
"map", BCON_CODE (MAPPER),
"reduce", BCON_CODE (REDUCER),
"out", "{", "inline", "1", "}");
read_pref = mongoc_read_prefs_new (MONGOC_READ_SECONDARY);
cursor = mongoc_database_command (database, MONGOC_QUERY_NONE, 0, 0, 0,
command, NULL, read_pref);
/* Do something with the results */
while (mongoc_cursor_next (cursor, &doc)) {
print_res (doc);
}
if (mongoc_cursor_error (cursor, &error)) {
fprintf (stderr, "ERROR: %s\n", error.message);
res = false;
}
mongoc_cursor_destroy (cursor);
mongoc_read_prefs_destroy (read_pref);
bson_destroy (command);
return res;
}
RUNNING¶
Here's how to run the example code/* * Copyright 2016 MongoDB, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE‐2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <mongoc.h> #include <stdio.h> #include "constants.c" #include "../doc‐common‐insert.c" #include "distinct.c" #include "map‐reduce‐basic.c" #include "map‐reduce‐advanced.c" int main (int argc, char *argv[]) { mongoc_database_t *database = NULL; mongoc_client_t *client = NULL; mongoc_collection_t *collection = NULL; char *host_and_port = NULL; int res = 0; if (argc != 2) { fprintf (stderr, "usage: %s CONNECTION‐STRING\n", argv[0]); fprintf (stderr, "the connection string can be of the following forms:\n"); fprintf (stderr, "localhost\t\t\t\tlocal machine\n"); fprintf (stderr, "localhost:27018\t\t\t\tlocal machine on port 27018\n"); fprintf (stderr, "mongodb://user:pass@localhost:27017\t" "local machine on port 27017, and authenticate with username " "user and password pass\n"); return 1; } mongoc_init (); if (strncmp (argv[1], "mongodb://", 10) == 0) { host_and_port = bson_strdup (argv [1]); } else { host_and_port = bson_strdup_printf ("mongodb://%s", argv[1]); } client = mongoc_client_new (host_and_port); if (!client) { fprintf (stderr, "Invalid hostname or port: %s\n", host_and_port); res = 2; goto cleanup; } mongoc_client_set_error_api (client, 2); database = mongoc_client_get_database (client, "test"); collection = mongoc_database_get_collection (database, COLLECTION_NAME); printf ("Inserting data\n"); if (!insert_data (collection)) { res = 3; goto cleanup; } printf ("distinct\n"); if (!distinct (database)) { res = 4; goto cleanup; } printf ("map reduce\n"); if (!map_reduce_basic (database)) { res = 5; goto cleanup; } printf ("more complicated map reduce\n"); if (!map_reduce_advanced (database)) { res = 6; goto cleanup; } cleanup: if (collection) { mongoc_collection_destroy (collection); } if (database) { mongoc_database_destroy (database); } if (client) { mongoc_client_destroy (client); } if (host_and_port) { bson_free (host_and_port); } mongoc_cleanup (); return res; }
If you want to try the advanced map reduce example with a secondary, start a replica set (instructions for how to do this can be found here ).
Otherwise, just start an instance of MongoDB:
$ mongod
Now compile and run the example program:
$ cd examples/basic_aggregation/ $ gcc -Wall -o agg-example basic-aggregation.c $(pkg-config --cflags --libs libmongoc-1.0) $ ./agg-example localhost
COLOPHON¶
This page is part of MongoDB C Driver. Please report any bugs at https://jira.mongodb.org/browse/CDRIVER.| 2016‐10‐12 | MongoDB C Driver |