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

用户名

我有一个来自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

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

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
            }
        }
    }
}
鲍曼空间

您需要下降两次,首先进入外部文档,然后进入内部文档。

libbson文档非常好。给mongodb工作人员的道具

这是一个完整的例子

#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”,则可以始终使用点符号find_descendant函数将显式的while循环转换为隐式(执行的库)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本身具有相同的许可。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何从Mongo DB集合中提取特定字段

来自分类Dev

如何更新 Mongo DB 中的字段?

来自分类Dev

Mongo 从多字段列中提取字段

来自分类Dev

mongo db 使用以数值开头的字段

来自分类Dev

如何从 Advantage SQL DB 的日期时间字段中提取日期

来自分类Dev

如何使用 sed 从分隔文件中提取字段

来自分类Dev

如何使用 sed 或 awk 从文件中提取字段

来自分类Dev

如何从mongo复杂子字段中提取数据?

来自分类Dev

节点-Mongo DB-如何查询特定的嵌套字段

来自分类Dev

如何在Mongo DB中合并数组和文档字段

来自分类Dev

mongo db聚合如何获取所有字段

来自分类Dev

MongoDB聚合:如何在结果中提取字段

来自分类Dev

如何从UnQLite集合中提取字段值

来自分类Dev

MongoDB聚合:如何在结果中提取字段

来自分类Dev

如何从编码的 JSON 对象中提取字段

来自分类Dev

使用sed或awk从文件中提取字段

来自分类Dev

按顺序从web2py db查询中提取字段名称

来自分类Dev

Mongo DB隔离的效率如何

来自分类Dev

Mongo DB隔离的效率如何

来自分类Dev

使用Mongo DB查询参考

来自分类Dev

在mongo db聚合中使用$ not

来自分类Dev

使用Mongo DB的PyTorch DataLoader

来自分类Dev

使用 Perl 的 Mongo DB JavaScript

来自分类Dev

Splunk:如何使用正则表达式直接在Search命令中提取字段?

来自分类Dev

使用 shell 命令如何从命令 (zdb) 中提取字段

来自分类Dev

在mongo db中选择嵌套字段

来自分类Dev

Mongo Db按索引字段搜索

来自分类Dev

Mongo db 项目不在组中的字段

来自分类Dev

如何使用公式(或表达式)通过Mongo DB C#Drivers 4.2更新值?