mongoc中, 要操作的数据都是bson_t.
bson_t的数据填充要使用mongoc的append系列函数.
bson_t中可以插入很复杂的数据结构, 可以用插入单个元素和插入数组来完成.
插入单个元素时, 用BSON_APPEND_X或bson_append_x
插入数组时, 用bson_append_array_begin和bson_append_array_end, 在begin和end之间, 插入单个元素.
结合mongoc的在线帮助和mongoc源码做了试验.
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <cstddef>
#include "MongoDbEx.h"
#include "BusinessLogic.h"
int testcase_mongoc_example_command_simple(int argc, char* argv[]);
int testcase_mongoc_example_document(int argc, char* argv[]);
int main(int argc, char* argv[])
{
printf("============================================================\n");
printf(">> testcase v1.0.0.5\n");
printf("============================================================\n");
testcase_mongoc_example_document(argc, argv);
// testcase_mongoc_example_command_simple(argc, argv);
printf("============================================================\n");
printf("END\n");
printf("============================================================\n");
return 0;
}
int testcase_mongoc_example_document(int argc, char* argv[])
{
TAG_PERSON_INFO person;
bson_t* document = NULL;
memset(&person, sizeof(person), 0);
person.birthday.tm_year = 1973 - 1900; // base 1900
person.birthday.tm_mon = 4;
person.birthday.tm_mday = 1;
person.name.first = "lostspeed";
person.name.last = "cn";
person.skillAry[0] = "C";
person.skillAry[1] = "C++";
person.skillAry[2] = "MASM";
person.skillAry[3] = "RE";
person.skillAry[4] = NULL; // !
person.degreeAry[0].degree = "graduates";
person.degreeAry[0].school = "zhongnian";
person.degreeAry[1].degree = "graduates";
person.degreeAry[1].school = "cr";
person.degreeAry[2].degree = NULL; // !
person.degreeAry[2].school = NULL; // !
document = bson_new();
fill_TAG_PERSON_INFO(document, &person);
// use document ...
ShowDocument("person", document);
/**
[person] {
"name" : { "first" : "lostspeed", "last" : "cn" },
"birthday" : { "$date" : 105087610000 },
"skill" : [ "C", "C++", "MASM", "RE" ],
"degrees" : [
{ "school" : "zhongnian", "degree" : "graduates" },
{ "school" : "cr", "degree" : "graduates" } ]
}
*/
bson_destroy(document);
return 0;
}
int testcase_mongoc_example_command_simple(int argc, char* argv[])
{
mongoc_client_t* client = NULL;
mongoc_database_t* database = NULL;
mongoc_collection_t* collection = NULL;
bson_t* insert = NULL;
bson_error_t error;
bool retval = false;
mongoc_init();
client = mongoc_client_new("mongodb://localhost:27017");
/*
* Register the application name so we can track it in the profile logs
* on the server. This can also be done from the URI (see other examples).
*/
mongoc_client_set_appname(client, "connect-example");
database = mongoc_client_get_database(client, "db_name");
collection = mongoc_client_get_collection(client, "db_name", "coll_name");
// cmd : ping
retval = DbOptExec_command_simple(client, "admin", "ping", &error);
if (!retval) {
ShowErrMsg("ping", &error);
return EXIT_FAILURE;
}
/**
[ping] { "ok" : 1.0 }
*/
insert = BCON_NEW("hello", BCON_UTF8("world"));
if (!mongoc_collection_insert(
collection, MONGOC_INSERT_NONE, insert, NULL, &error)) {
ShowErrMsg("mongoc_collection_insert", &error);
}
// cmd : buildinfo
bson_destroy(insert);
retval = DbOptExec_command_simple(client, "admin", "buildinfo", &error);
if (!retval) {
ShowErrMsg("buildinfo", &error);
}
/**
[buildinfo] {
"version" : "2.6.10",
"gitVersion" : "5901dbfb49d16eaef6f2c2c50fba534d23ac7f6c",
"OpenSSLVersion" : "",
"sysInfo" : "Linux build18.nj1.10gen.cc 2.6.32-431.3.1.el6.x86_64 #1 SMP Fri Jan 3 21:39:27 UTC 2014 x86_64 BOOST_LIB_VERSION=1_49",
"loaderFlags" : "-fPIC -pthread -Wl,-z,now -rdynamic",
"compilerFlags" : "-Wnon-virtual-dtor -Woverloaded-virtual -fPIC -fno-strict-aliasing -ggdb -pthread -Wall -Wsign-compare -Wno-unknown-pragmas -Winvalid-pch -pipe -Werror -O3 -Wno-unused-function -Wno-deprecated-declarations -fno-builtin-memcmp",
"allocator" : "tcmalloc",
"versionArray" : [ 2, 6, 10, 0 ],
"javascriptEngine" : "V8",
"bits" : 64,
"debug" : false,
"maxBsonObjectSize" : 16777216,
"ok" : 1.0 }
*/
// cmd : serverStatus
retval = DbOptExec_command_simple(client, "admin", "serverStatus", &error);
if (!retval) {
ShowErrMsg("serverStatus", &error);
}
/**
[serverStatus]
{
"host" : "debian",
"version" : "2.6.10",
"process" : "mongod",
"pid" : 3243,
"uptime" : 21899.0,
"uptimeMillis" : 21897854,
"uptimeEstimate" : 19920.0,
"localTime" : { "$date" : 1491227764737 },
"asserts" : { "regular" : 0, "warning" : 0, "msg" : 0, "user" : 0, "rollovers" : 0 },
"backgroundFlushing" : { "flushes" : 364, "total_ms" : 54, "average_ms" : 0.14835164835164835195, "last_ms" : 0, "last_finished" : { "$date" : 1491227708337 } },
"connections" : { "current" : 1, "available" : 818, "totalCreated" : 9 },
"cursors" : { "note" : "deprecated, use server status metrics", "clientCursors_size" : 0, "totalOpen" : 0, "pinned" : 0, "totalNoTimeout" : 0, "timedOut" : 0 },
"dur" : { "commits" : 29, "journaledMB" : 0.0, "writeToDataFilesMB" : 0.0, "compression" : 0.0, "commitsInWriteLock" : 0, "earlyCommits" : 0,
"timeMs" : { "dt" : 3044, "prepLogBuffer" : 0, "writeToJournal" : 0, "writeToDataFiles" : 0, "remapPrivateView" : 0 } },
"extra_info" : { "note" : "fields vary by platform", "heap_usage_bytes" : 62725408, "page_faults" : 98 },
"globalLock" : { "totalTime" : 21897856000, "lockTime" : 5334268,
"currentQueue" : { "total" : 0, "readers" : 0, "writers" : 0 },
"activeClients" : { "total" : 0, "readers" : 0, "writers" : 0 } },
"indexCounters" : { "accesses" : 19, "hits" : 19, "misses" : 0, "resets" : 0, "missRatio" : 0.0 },
"locks" : { "." : {
"timeLockedMicros" : { "R" : 435761, "W" : 5334268 },
"timeAcquiringMicros" : { "R" : 4899977, "W" : 2994540 } },
"admin" : { "timeLockedMicros" : { "r" : 151982, "w" : 0 },
"timeAcquiringMicros" : { "r" : 369253, "w" : 0 } },
"local" : { "timeLockedMicros" : { "r" : 128739, "w" : 83 }, "timeAcquiringMicros" : { "r" : 54838, "w" : 1 } },
"testdb" : { "timeLockedMicros" : { "r" : 2081468, "w" : 130 }, "timeAcquiringMicros" : { "r" : 19698, "w" : 3 } },
"mongodb" : { "timeLockedMicros" : { "r" : 191151, "w" : 128 }, "timeAcquiringMicros" : { "r" : 30413, "w" : 4 } },
"db_name" : { "timeLockedMicros" : { "r" : 375654, "w" : 908 }, "timeAcquiringMicros" : { "r" : 14419, "w" : 40 } },
"Barca" : { "timeLockedMicros" : { "r" : 158307, "w" : 134 }, "timeAcquiringMicros" : { "r" : 19699, "w" : 3 } },
"dbs" : { "timeLockedMicros" : { "r" : 610389, "w" : 224 }, "timeAcquiringMicros" : { "r" : 17663, "w" : 6 } },
"test1" : { "timeLockedMicros" : { "r" : 829203, "w" : 28 }, "timeAcquiringMicros" : { "r" : 15951, "w" : 2 } },
"yekai" : { "timeLockedMicros" : { "r" : 2065973, "w" : 269 }, "timeAcquiringMicros" : { "r" : 61179, "w" : 4 } },
"tutorial" : { "timeLockedMicros" : { "r" : 1491259, "w" : 157 }, "timeAcquiringMicros" : { "r" : 28555, "w" : 3 } } },
"network" : { "bytesIn" : 5730, "bytesOut" : 13310, "numRequests" : 44 },
"opcounters" : { "insert" : 9, "query" : 3641, "update" : 0, "delete" : 0, "getmore" : 0, "command" : 38 },
"opcountersRepl" : { "insert" : 0, "query" : 0, "update" : 0, "delete" : 0, "getmore" : 0, "command" : 0 },
"recordStats" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0,
"Barca" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
"admin" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
"db_name" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
"dbs" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
"local" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
"mongodb" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
"test1" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
"testdb" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
"tutorial" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 },
"yekai" : { "accessesNotInMemory" : 0, "pageFaultExceptionsThrown" : 0 } },
"writeBacksQueued" : false,
"mem" : { "bits" : 64, "resident" : 158, "virtual" : 62683, "supported" : true, "mapped" : 31251, "mappedWithJournal" : 62502 },
"metrics" : { "cursor" : { "timedOut" : 0, "open" : { "noTimeout" : 0, "pinned" : 0, "total" : 0 } },
"document" : { "deleted" : 0, "inserted" : 9, "returned" : 0, "updated" : 0 },
"getLastError" : { "wtime" : { "num" : 0, "totalMillis" : 0 }, "wtimeouts" : 0 },
"operation" : { "fastmod" : 0, "idhack" : 0, "scanAndOrder" : 0 },
"queryExecutor" : { "scanned" : 0, "scannedObjects" : 0 },
"record" : { "moves" : 0 },
"repl" : {
"apply" : { "batches" : { "num" : 0, "totalMillis" : 0 }, "ops" : 0 },
"buffer" : { "count" : 0, "maxSizeBytes" : 268435456, "sizeBytes" : 0 },
"network" : { "bytes" : 0, "getmores" : { "num" : 0, "totalMillis" : 0 }, "ops" : 0, "readersCreated" : 0 },
"preload" : { "docs" : { "num" : 0, "totalMillis" : 0 }, "indexes" : { "num" : 0, "totalMillis" : 0 } } },
"storage" : { "freelist" : { "search" : { "bucketExhausted" : 0, "requests" : 8, "scanned" : 16 } } },
"ttl" : { "deletedDocuments" : 0, "passes" : 364 } },
"ok" : 1.0 }
*/
// cmd : ismaster
retval = DbOptExec_command_simple(client, "admin", "ismaster", &error);
if (!retval) {
ShowErrMsg("ismaster", &error);
}
/**
[ismaster] {
"ismaster" : true,
"maxBsonObjectSize" : 16777216,
"maxMessageSizeBytes" : 48000000,
"maxWriteBatchSize" : 1000,
"localTime" : { "$date" : 1491230240360 },
"maxWireVersion" : 2,
"minWireVersion" : 0,
"ok" : 1.0
}
*/
// cmd : getlasterror
retval = DbOptExec_command_simple(client, "admin", "getlasterror", &error);
if (!retval) {
ShowErrMsg("getlasterror", &error);
}
/**
[getlasterror] {
"connectionId" : 11,
"n" : 0,
"syncMillis" : 0,
"writtenTo" : null,
"err" : null,
"ok" : 1.0
}
*/
// cmd : foo
retval = DbOptExec_command_simple(client, "admin", "foo", &error);
if (!retval) {
ShowErrMsg("foo", &error);
}
/**
[foo] error : no such cmd: foo
*/
// cmd : empty
// 空命令会报错的
// retval = DbOptExec_command_simple(client, "admin", "{}", &error);
//
// if (!retval) {
// ShowErrMsg("{}", &error);
// }
// cmd : empty
retval = DbOptExec_command_simple(client, "admin", "", &error);
if (!retval) {
ShowErrMsg("", &error);
}
/**
[] error : no such cmd:
*/
// cmd : db
retval = DbOptExec_command_simple(client, "admin", "db", &error);
if (!retval) {
ShowErrMsg("db", &error);
}
/**
[db] error : no such cmd: db
*/
/**
MongoDB shell version: 2.6.10
connecting to: test
> show dbs
Barca 0.078GB
admin 0.078GB
db_name 0.078GB
local 0.078GB
mongodb 0.078GB
test1 0.078GB
testdb 0.078GB
tutorial 0.078GB
yekai 7.950GB
>
> use test1
switched to db test1
> show collections
system.indexes
test1
>
*/
// cmd : "{'drop': '%s'}"
retval = DbOptExec_command_simple(client, "admin", "use", "test1", &error);
if (!retval) {
ShowErrMsg("use test1", &error);
}
/**
[use test1] error : no such cmd: use
*/
retval = DbOptExec_command_simple(client, "test1", "drop", "test1", &error);
if (!retval) {
ShowErrMsg("drop test1", &error);
}
/**
[drop] { "ns" : "test1.test1", "nIndexesWas" : 1, "ok" : 1.0 }
*/
/** mongo console
> use test1
switched to db test1
> show collections
system.indexes
>
*/
// cmd : getCmdLineOpts
retval = DbOptExec_command_simple(client, "admin", "getCmdLineOpts", &error);
if (!retval) {
ShowErrMsg("getCmdLineOpts", &error);
}
/**
[getCmdLineOpts] {
"argv" : [ "\/usr\/local\/mongodb\/bin\/mongod", "--config", "\/usr\/local\/mongodb\/bin\/mongodb.conf" ],
"parsed" : {
"config" : "\/usr\/local\/mongodb\/bin\/mongodb.conf",
"net" : { "http" : { "enabled" : false }, "port" : 27017 },
"processManagement" : { "fork" : true },
"storage" : { "dbPath" : "\/usr\/local\/mongodb\/db" },
"systemLog" : { "destination" : "file", "path" : "\/usr\/local\/mongodb\/logs\/mongodb.log" }
},
"ok" : 1.0
}
*/
mongoc_collection_destroy(collection);
mongoc_database_destroy(database);
mongoc_client_destroy(client);
mongoc_cleanup();
return 0;
}
// BusinessLogic.h: interface for the BusinessLogic class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_BUSINESSLOGIC_H__91436BA7_97DD_495E_A750_A141145804E1__INCLUDED_)
#define AFX_BUSINESSLOGIC_H__91436BA7_97DD_495E_A750_A141145804E1__INCLUDED_
#include <bson.h>
#include <bcon.h>
#include <mongoc.h>
#ifndef BOOL
typedef bool BOOL;
#define TRUE 1
#define FALSE 0
#endif // #ifndef BOOL
typedef struct _tag_name {
const char* first;
const char* last;
} TAG_NAME;
typedef struct _tag_degress {
const char* school;
const char* degree;
} TAG_DEGRESS;
typedef struct _tag_person_info {
TAG_NAME name;
struct tm birthday;
const char* skillAry[10];
TAG_DEGRESS degreeAry[10];
} TAG_PERSON_INFO;
void fill_TAG_PERSON_INFO(bson_t* document, TAG_PERSON_INFO* person);
#endif // !defined(AFX_BUSINESSLOGIC_H__91436BA7_97DD_495E_A750_A141145804E1__INCLUDED_)
// BusinessLogic.cpp: implementation of the BusinessLogic class.
//
//////////////////////////////////////////////////////////////////////
#include "BusinessLogic.h"
void fill_TAG_PERSON_INFO(bson_t* document, TAG_PERSON_INFO* person)
{
int i = 0;
int iArySize = 0;
bson_t child;
bson_t child2;
const char* key = NULL;
size_t keylen = 0;
char buf[32] = {'\0'};
if ((NULL == document) || (NULL == person)) {
return;
}
bson_append_document_begin(document, "name", -1, &child);
BSON_APPEND_UTF8(&child, "first", person->name.first);
BSON_APPEND_UTF8(&child, "last", person->name.last);
bson_append_document_end(document, &child);
BSON_APPEND_DATE_TIME(document, "birthday", mktime(&person->birthday) * 1000);
bson_append_array_begin(document, "skill", -1, &child);
iArySize = sizeof(person->skillAry) / sizeof(char*);
for (i = 0; i < iArySize; i++) {
if (NULL == person->skillAry[i]) {
break;
}
keylen = bson_uint32_to_string(i + 1, &key, buf, sizeof buf);
bson_append_utf8(&child, key, (int) keylen, person->skillAry[i], -1);
}
bson_append_array_end(document, &child);
bson_append_array_begin(document, "degrees", -1, &child);
iArySize = sizeof(person->degreeAry) / sizeof(TAG_DEGRESS);
for (i = 0; i < iArySize; i++) {
if ((NULL == person->degreeAry[i].degree) || (NULL == person->degreeAry[i].school)) {
break;
}
bson_append_document_begin(&child, "", -1, &child2);
bson_append_utf8(&child2, "school", -1, person->degreeAry[i].school, -1);
bson_append_utf8(&child2, "degree", -1, person->degreeAry[i].degree, -1);
bson_append_document_end(&child, &child2);
}
bson_append_array_end(document, &child);
}
// @file MongoDbEx.h
// @brief MongoDB operation
#ifndef __MONGODB_EX__
#define __MONGODB_EX__
#include <bson.h>
#include <bcon.h>
#include <mongoc.h>
#ifndef BOOL
typedef bool BOOL;
#define TRUE 1
#define FALSE 0
#endif // #ifndef BOOL
BOOL DbOptInit();
BOOL DbOptUnInit();
mongoc_client_t* DbOptOpenConect(const char* pConnectUrl);
void DbOptCloseConect(mongoc_client_t*& pDbConnect);
mongoc_database_t* DbOptOpenDb(mongoc_client_t* pDbConnect, const char* pDbName);
void DbOptCloseDb(mongoc_database_t*& pDb);
mongoc_collection_t* DbOptOpenTbl(mongoc_database_t* pDb, const char* pTblName);
void DbOptCloseTbl(mongoc_collection_t*& pTbl);
bool DbOptExec_command_simple(
mongoc_client_t* pClient,
const char* pcDbName,
const char* pcCommand,
bson_error_t* pError);
bool DbOptExec_command_simple(
mongoc_client_t* pClient,
const char* pcDbName,
const char* pcCommand,
const char* pcValue,
bson_error_t* pError);
void ShowErrMsg(const char* pTip, bson_error_t* error);
void ShowReply(const char* pTip, bson_t* reply);
void ShowDocument(const char* pTip, bson_t* document);
bson_t* new_formatv_bson(const char* json, ...);
char* single_quotes_to_double(const char* str);
#endif // #ifndef __MONGODB_EX__
// @file MongoDbEx.cpp
// @brief ...
#include "MongoDbEx.h"
BOOL DbOptInit()
{
mongoc_init();
}
BOOL DbOptUnInit()
{
mongoc_cleanup();
}
mongoc_client_t* DbOptOpenConect(const char* pConnectUrl)
{
mongoc_client_t* pDbClient = NULL;
if (NULL != pConnectUrl) {
pDbClient = mongoc_client_new(pConnectUrl);
}
return pDbClient;
}
void DbOptCloseConect(mongoc_client_t*& pDbConnect)
{
if (NULL != pDbConnect) {
mongoc_client_destroy(pDbConnect);
pDbConnect = NULL;
}
}
mongoc_database_t* DbOptOpenDb(mongoc_client_t* pDbConnect, const char* pDbName)
{
mongoc_database_t* pDb = NULL;
if (NULL != pDbConnect) {
pDb = mongoc_client_get_database(pDbConnect, pDbName);
}
return pDb;
}
void DbOptCloseDb(mongoc_database_t*& pDb)
{
if (NULL != pDb) {
mongoc_database_destroy(pDb);
pDb = NULL;
}
}
mongoc_collection_t* DbOptOpenTbl(mongoc_database_t* pDb, const char* pTblName)
{
mongoc_collection_t* pTbl = NULL;
pTbl = mongoc_database_get_collection(pDb, pTblName);
return pTbl;
}
void DbOptCloseTbl(mongoc_collection_t*& pTbl)
{
if (NULL != pTbl) {
mongoc_collection_destroy(pTbl);
pTbl = NULL;
}
}
bool DbOptExec_command_simple(
mongoc_client_t* pClient,
const char* pcDbName,
const char* pcCommand,
bson_error_t* pError)
{
bool retval = false;
bson_t* command = NULL;
bson_t reply;
do {
command = BCON_NEW(pcCommand, BCON_INT32(1));
// mongoc_client_command_simple 作用: 让mongodb执行一些命令, 返回一些结果
retval = mongoc_client_command_simple(pClient, pcDbName, command, NULL, &reply, pError);
if (!retval) {
break;
} else {
ShowReply(pcCommand, &reply);
}
} while (0);
bson_destroy(&reply);
bson_destroy(command);
return retval;
}
bool DbOptExec_command_simple(
mongoc_client_t* pClient,
const char* pcDbName,
const char* pcCommand,
const char* pcValue,
bson_error_t* pError)
{
bool retval = false;
bson_t reply;
bson_t* doc = NULL;
char* sz_cmd = NULL;
do {
// mongoc_client_command_simple 作用: 让mongodb执行一些命令, 返回一些结果
sz_cmd = bson_strdup_printf("{'%s': '%s'}", pcCommand, pcValue);
doc = new_formatv_bson("%s", sz_cmd);
retval = mongoc_client_command_simple(pClient, pcDbName, doc, NULL, &reply, pError);
bson_free(sz_cmd);
if (!retval) {
break;
} else {
ShowReply(pcCommand, &reply);
}
} while (0);
bson_destroy(&reply);
bson_destroy(doc);
return retval;
}
void ShowErrMsg(const char* pTip, bson_error_t* error)
{
if (NULL != error) {
fprintf(stderr, "[%s] error : %s\n\n", (NULL != pTip) ? pTip : "", error->message);
}
}
void ShowReply(const char* pTip, bson_t* reply)
{
char* str = NULL;
if (NULL != reply) {
str = bson_as_json(reply, NULL);
if (NULL != str) {
printf("[%s] %s\n\n", (NULL != pTip) ? pTip : "", str);
bson_free(str);
}
}
}
void ShowDocument(const char* pTip, bson_t* document)
{
char* str = NULL;
if (NULL != document) {
str = bson_as_json(document, NULL);
if (NULL != str) {
printf("[%s] %s\n\n", (NULL != pTip) ? pTip : "", str);
bson_free(str);
}
}
}
bson_t* new_formatv_bson(const char* json, ...)
{
va_list args;
bson_error_t error;
char* formatted;
char* double_quoted;
bson_t* doc;
if (json) {
va_start(args, json);
formatted = bson_strdupv_printf(json, args);
va_end(args);
double_quoted = single_quotes_to_double(formatted);
doc = bson_new_from_json((const uint8_t*) double_quoted, -1, &error);
if (!doc) {
fprintf(stderr, "%s\n", error.message);
abort();
}
bson_free(formatted);
bson_free(double_quoted);
} else {
doc = bson_new();
}
return doc;
}
char* single_quotes_to_double(const char* str)
{
char* result = bson_strdup(str);
char* p;
for (p = result; *p; p++) {
if (*p == '\'') {
*p = '"';
}
}
return result;
}