如何使用C libbson从mongo db change流中提取字段

问题描述 投票:0回答:1

我有一个来自mongo db更改流的bson_t“ b”,由bson_as_canonical_extended_json这样打印:

{ "_id" : { "_data" : "825ECC4FEA0000002E2B022C0100296E5A10044A1DE2ECB8554397B8F
03E803FB80F1F463C5F6964003C3030313330323637000004" },   
"operationType" : "update",   
"clusterTime" : { "$timestamp" : { "t" : 1590448106, "i" : 46 } },   
"ns" : { "db" : "test", "coll" : "my_collection" },   
"documentKey" : { "_id" : "00130267" },   
"updateDescription" : { "updatedFields" : { "0x000F" : "25.006001", "0x0010" : "24.976000" },  
 "removedFields" : [  ] } }  

我可以这样进入“ documentKey”字段:

bson_iter_t iter;
if (bson_iter_init_find(&iter, b, "documentKey"))
bson_iter_t child;
if (bson_iter_recurse(&iter, &child))
{
    while (bson_iter_next(&child))
    {
        const bson_value_t *value = bson_iter_value(&child);
        printf("documentKey sub-key %s value %s\n", bson_iter_key(&child), (char*)value->value.v_utf8.str);
    }
}

打印“ _id”:“ 00130267”如何访问“ updateDescription”字段,到处都有示例这个结构不是我选择的,它来自mongo db change stream

鲍曼(Bauman)后来的回答更加严格,对我来说,这是可行的:

bson_iter_t iter1;
if (bson_iter_init_find(&iter1, b, "updateDescription")) // doc 
{
    bson_iter_t child1;
    if (bson_iter_recurse(&iter1, &child1))
    {
        while (bson_iter_next(&child1))// updatedFields doc
        {
            bson_iter_t child2;
            bson_iter_recurse(&child1, &child2);
            while (bson_iter_next(&child2))
            {
                const bson_value_t *value = bson_iter_value(&child2);
                printf("updateDescription arr %s value %s\n", bson_iter_key(&child2), (char*)value->value.v_utf8.str);// key and value of the array
            }
        }
    }
}
c mongodb bson
1个回答
0
投票
#include <bson.h> void descending_to_updateDescription(bson_t *b){ bson_iter_t change_iter; if (bson_iter_init_find(&change_iter, b, "updateDescription")) { bson_iter_t desired_field; if (bson_iter_recurse(&change_iter, &desired_field)) { // "updateDescription" : { "updatedFields" : { "0x000F" : "25.006001", "0x0010" : "24.976000" }, "removedFields" : [ ] } // (key) ^ (value) // pointer is now here | (at the beginning of the document // confirm the (value) is type DOCUMENT as we expect (containing keys, "updateFields" and "removedFields" if BSON_ITER_HOLDS_DOCUMENT(&change_iter){ while (bson_iter_next(&desired_field)) { // printing the outer key (expect 2, shown below) printf("%s\n", bson_iter_key(&desired_field)); // first loop // "updateDescription" : { "updatedFields" : { "0x000F" : "25.006001", "0x0010" : "24.976000" }, "removedFields" : [ ] } // (key) ^ (value) -- another document // pointer is now here ----------------- | // // next loop // "updateDescription" : { "updatedFields" : { "0x000F" : "25.006001", "0x0010" : "24.976000" }, "removedFields" : [ ] } // (key) ^ (value) - a list // pointer is now waaaaaaaaaayyyyyyyy ovvvvvveeeeerrr here --------------------------------------------------- | // next loop // "updateDescription" : { "updatedFields" : { "0x000F" : "25.006001", "0x0010" : "24.976000" }, "removedFields" : [ ] } // ^ // pointer is now waaaaaaaaaayyyyyyyy ovvvvvveeeeerrr here ---------------------------------------------------------- | (end of document // iter_next returns false, because no other keys in the outer dict // descend into the next level down bson_iter_t changefields_iter; // SUPER IMPORTANT, recurese from desired_field, not from the original change iter! if (bson_iter_recurse(&desired_field, &changefields_iter)){ // "updateDescription" : { "updatedFields" : { "0x000F" : "25.006001", "0x0010" : "24.976000" }, "removedFields" : [ ] } // (key) ^ (value) - a document // pointer is now here -------------------- | // expect update fields to hold a documnet, and removeFields to hold a list, skip processing remove fields while (bson_iter_next(&changefields_iter)) { // first loop // "updateDescription" : { "updatedFields" : { "0x000F" : "25.006001", "0x0010" : "24.976000" }, "removedFields" : [ ] } // (key) ^ (value) - a string in this example // pointer is now here --------------------------------| // second loop // "updateDescription" : { "updatedFields" : { "0x000F" : "25.006001", "0x0010" : "24.976000" }, "removedFields" : [ ] } // (key) ^ (value) - a string in this example // pointer is now here --------------------------------------------------------| // third loop // "updateDescription" : { "updatedFields" : { "0x000F" : "25.006001", "0x0010" : "24.976000" }, "removedFields" : [ ] } // ^ // pointer is now here ----------------------------------------------------------------------| (end of document) // Example looks like we expect string values, so check for it if (BSON_ITER_HOLDS_UTF8(&changefields_iter)){ uint32_t length; // iterating the string object can give you length, we don't need it though because we're not strncopying printf( "\tKey: %s \t Value: %s\n", bson_iter_key(&changefields_iter), bson_iter_utf8(&changefields_iter, &length) ); } } } } } } } } int main(){ // just setting up char * json_data = "{ \"_id\" : { \"_data\" : \"825ECC4FEA0000002E2B022C0100296E5A10044A1DE2ECB8554397B8F03E803FB80F1F463C5F6964003C3030313330323637000004\" }, \"operationType\" : \"update\", \"clusterTime\" : { \"$timestamp\" : { \"t\" : 1590448106, \"i\" : 46 } }, \"ns\" : { \"db\" : \"test\", \"coll\" : \"my_collection\" }, \"documentKey\" : { \"_id\" : \"00130267\" }, \"updateDescription\" : { \"updatedFields\" : { \"0x000F\" : \"25.006001\", \"0x0010\" : \"24.976000\" }, \"removedFields\" : [ ] } }" ; bson_error_t error; bson_t *b; b = bson_new_from_json ((uint8_t*)json_data, -1, &error); descending_to_updateDescription(b); bson_destroy(b); b = NULL; // explicit nulled in case this is extended later return 0; }

这是输出

updatedFields Key: 0x000F Value: 25.006001 Key: 0x0010 Value: 24.976000 removedFields Process finished with exit code 0

重要的事实是第二次下降。

当您找到并递归到updateDescription时,还需要再次下降到UpdatedFields / updatedFields文档中,以将其打印出来。

[此外,如果您真的只想检查“ updateFields”,则可以始终使用dot notationfind_descendant函数将显式的while循环转换为隐式(执行的库)。您的代码看起来更简洁,但是您这样做并没有节省任何性能,该库正在执行与上例相同的循环

#include <bson.h>
void descending_direct_to_updateFields(bson_t *b){
    bson_iter_t change_iter;
    bson_iter_t updateFields_iter;
    // use the find_descendant function
    if (bson_iter_init(&change_iter, b) && bson_iter_find_descendant(&change_iter, "updateDescription.updatedFields", &updateFields_iter)) {
        // "updateDescription" : { "updatedFields" : { "0x000F" : "25.006001", "0x0010" : "24.976000" }, "removedFields" : [  ] }
        //                                  (key)  ^   (value) - document with 2 keys
        // pointer is now here  -------------------|
        printf("%s\n", "updateDescription.updatedFields"); // just print because you looked for it
        if BSON_ITER_HOLDS_DOCUMENT(&updateFields_iter){
            bson_iter_t desired_field;
            bson_iter_recurse(&updateFields_iter, &desired_field);
            while (bson_iter_next(&desired_field)) {
                if (BSON_ITER_HOLDS_UTF8(&desired_field)) {
                    uint32_t length; // iterating the string object can give you length, we don't need it though because we're not strncopying
                    printf(
                            "\tKey: %s \t Value: %s\n",
                            bson_iter_key(&desired_field),
                            bson_iter_utf8(&desired_field, &length)
                    );
                }
            }
        }
    }
}

int main(){
    // just setting up
    char * json_data = "{ \"_id\" : { \"_data\" : \"825ECC4FEA0000002E2B022C0100296E5A10044A1DE2ECB8554397B8F03E803FB80F1F463C5F6964003C3030313330323637000004\" }, \"operationType\" : \"update\", \"clusterTime\" : { \"$timestamp\" : { \"t\" : 1590448106, \"i\" : 46 } }, \"ns\" : { \"db\" : \"test\", \"coll\" : \"my_collection\" }, \"documentKey\" : { \"_id\" : \"00130267\" }, \"updateDescription\" : { \"updatedFields\" : { \"0x000F\" : \"25.006001\", \"0x0010\" : \"24.976000\" }, \"removedFields\" : [  ] } }" ;
    bson_error_t error;
    bson_t      *b;
    b = bson_new_from_json ((uint8_t*)json_data, -1, &error);
    descending_direct_to_updateFields(b);
    bson_destroy(b);
    b = NULL; // explicit nulled in case this is extended later
    return 0;
}

这是输出

updateDescription.updatedFields Key: 0x000F Value: 25.006001 Key: 0x0010 Value: 24.976000

堆栈溢出默认为这些答案提供了一个过度保护的许可证。在允许的范围内,我将所有答案中的所有代码和单词都放入了公共领域。在不允许或不承认公共领域的情况下,代码和文字与libbson本身使用的许可相同。
© www.soinside.com 2019 - 2024. All rights reserved.