由于工作需要将一条Mongo数据库的查询记录,输出成脚本格式。现记录关键代码,方便使用。Mongo数据库 C语言驱动的基础使用不做介绍。
用例数据:
/* Create a rich document like this one:
*
* { _id: ObjectId("4d95ea712b752328eb2fc2cc"),
* user_id: ObjectId("4d95ea712b752328eb2fc2cd"),
*
* items: [
* { sku: "col-123",
* name: "John Coltrane: Impressions",
* price: 1099,
* },
*
* { sku: "young-456",
* name: "Larry Young: Unity",
* price: 1199
* }
* ],
*
* address: {
* street: "59 18th St.",
* zip: 10010
* },
*
* total: 2298
* }
*/
bson_init( &b );
bson_append_new_oid( &b, "_id" );
bson_append_new_oid( &b, "user_id" );
bson_append_start_array( &b, "items" );
bson_append_start_object( &b, "book0" );
bson_append_string( &b, "sku", "col-123" );
bson_append_string( &b, "name", "John Coltrane: Impressions" );
bson_append_int( &b, "price", 1099 );
bson_append_finish_object( &b );
bson_append_start_object( &b, "book1" );
bson_append_string( &b, "sku", "young-456" );
bson_append_string( &b, "name", "Larry Young: Unity" );
bson_append_int( &b, "price", 1199 );
bson_append_finish_object( &b );
bson_append_finish_object( &b );
bson_append_start_object( &b, "address" );
bson_append_string( &b, "street", "59 18th St." );
bson_append_int( &b, "zip", 10010 );
bson_append_finish_object( &b );
bson_append_int( &b, "total", 2298 );
bson_finish( &b );
格式输出函数借鉴的Mongo C驱动源码如下:
MONGO_EXPORT void bson_print_raw( const char *data , int depth ) {
bson_iterator i;
const char *key;
int temp;
bson_timestamp_t ts;
char oidhex[25];
bson scope;
bson_iterator_from_buffer( &i, data );
while ( bson_iterator_next( &i ) ) {
bson_type t = bson_iterator_type( &i );
if ( t == 0 )
break;
key = bson_iterator_key( &i );
for ( temp=0; temp<=depth; temp++ )
bson_printf( "\t" );
bson_printf( "%s : %d \t " , key , t );
switch ( t ) {
case BSON_DOUBLE:
bson_printf( "%f" , bson_iterator_double( &i ) );
break;
case BSON_STRING:
bson_printf( "%s" , bson_iterator_string( &i ) );
break;
case BSON_SYMBOL:
bson_printf( "SYMBOL: %s" , bson_iterator_string( &i ) );
break;
case BSON_OID:
bson_oid_to_string( bson_iterator_oid( &i ), oidhex );
bson_printf( "%s" , oidhex );
break;
case BSON_BOOL:
bson_printf( "%s" , bson_iterator_bool( &i ) ? "true" : "false" );
break;
case BSON_DATE:
bson_printf( "%ld" , ( long int )bson_iterator_date( &i ) );
break;
case BSON_BINDATA:
bson_printf( "BSON_BINDATA" );
break;
case BSON_UNDEFINED:
bson_printf( "BSON_UNDEFINED" );
break;
case BSON_NULL:
bson_printf( "BSON_NULL" );
break;
case BSON_REGEX:
bson_printf( "BSON_REGEX: %s", bson_iterator_regex( &i ) );
break;
case BSON_CODE:
bson_printf( "BSON_CODE: %s", bson_iterator_code( &i ) );
break;
case BSON_CODEWSCOPE:
bson_printf( "BSON_CODE_W_SCOPE: %s", bson_iterator_code( &i ) );
/* bson_init( &scope ); */ /* review - stepped on by bson_iterator_code_scope? */
bson_iterator_code_scope( &i, &scope );
bson_printf( "\n\t SCOPE: " );
bson_print( &scope );
/* bson_destroy( &scope ); */ /* review - causes free error */
break;
case BSON_INT:
bson_printf( "%d" , bson_iterator_int( &i ) );
break;
case BSON_LONG:
bson_printf( "%lld" , ( uint64_t )bson_iterator_long( &i ) );
break;
case BSON_TIMESTAMP:
ts = bson_iterator_timestamp( &i );
bson_printf( "i: %d, t: %d", ts.i, ts.t );
break;
case BSON_OBJECT:
case BSON_ARRAY:
bson_printf( "\n" );
bson_print_raw( bson_iterator_value( &i ) , depth + 1 );
break;
default:
bson_errprintf( "can't print type : %d\n" , t );
}
bson_printf( "\n" );
}
}
修改之后的接口:
void bson_print_raw_to_string( const char *data , const string& strPrefix, string& strOutput ) {
bson_iterator i;
const char *key;
bson_timestamp_t ts;
char oidhex[25];
const int nOutputSize = 1024;
char szOutput[nOutputSize] = {0};
bson scope;
bson_iterator_from_buffer( &i, data );
while ( bson_iterator_next( &i ) ) {
bson_type t = bson_iterator_type( &i );
if ( t == 0 )
break;
key = bson_iterator_key( &i );
switch ( t ) {
case BSON_DOUBLE:
sprintf_s( szOutput, nOutputSize, "%f" , bson_iterator_double( &i ) );
break;
case BSON_STRING:
sprintf_s( szOutput, nOutputSize, "%s" , bson_iterator_string( &i ) );
break;
case BSON_SYMBOL:
sprintf_s( szOutput, nOutputSize, "%s" , bson_iterator_string( &i ) );
break;
case BSON_OID:
bson_oid_to_string( bson_iterator_oid( &i ), oidhex );
sprintf_s( szOutput, nOutputSize, "%s" , oidhex );
break;
case BSON_BOOL:
sprintf_s( szOutput, nOutputSize, "%s" , bson_iterator_bool( &i ) ? "true" : "false" );
break;
case BSON_DATE:
sprintf_s( szOutput, nOutputSize, "%ld" , ( long int )bson_iterator_date( &i ) );
break;
case BSON_INT:
sprintf_s( szOutput, nOutputSize, "%d" , bson_iterator_int( &i ) );
break;
case BSON_LONG:
sprintf_s( szOutput, nOutputSize, "%lld" , ( uint64_t )bson_iterator_long( &i ) );
break;
case BSON_TIMESTAMP:
ts = bson_iterator_timestamp( &i );
sprintf_s( szOutput, nOutputSize, "i: %d, t: %d", ts.i, ts.t );
break;
case BSON_OBJECT:
case BSON_ARRAY:
if (!strPrefix.empty())
{
bson_print_raw_to_string( bson_iterator_value( &i ) , strPrefix+"."+string(key), strOutput );
}
else
{
bson_print_raw_to_string( bson_iterator_value( &i ) , string(key), strOutput );
}
break;
default:
break;
}
string strValue(szOutput);
if (!strValue.empty())
{
if (!strPrefix.empty())
{
strOutput += strPrefix + "." + string(key) + ":=\"" + strValue + "\";\n";
}
else
{
strOutput += string(key) + ":=\"" + strValue + "\";\n";
}
}
memset(szOutput, 0, nOutputSize);
}
}
上面只处理了我需要使用的Mongo字段参数类型,其它字段可参照驱动源码自行添加。将上方的用例调用修改后的接口查询输出后,显示如下:
_id:="5560c19b4278000000000000";
user_id:="5560c19b4278000000000001";
items.book0.sku:="col-123";
items.book0.name:="John Coltrane: Impressions";
items.book0.price:="1099";
items.book1.sku:="young-456";
items.book1.name:="Larry Young: Unity";
items.book1.price:="1199";
address.street:="59 18th St.";
address.zip:="10010";
total:="2298";