您可以更改 bsoncxx 对象(文档/值/元素)吗?

Posted

技术标签:

【中文标题】您可以更改 bsoncxx 对象(文档/值/元素)吗?【英文标题】:Can you change a bsoncxx object (document/value/element)? 【发布时间】:2016-10-22 18:48:15 【问题描述】:

我正在使用 mongocxx 驱动程序,我正在考虑将 BSON 中给出的查询结果作为数据持有者保留在几个对象中,而不是解析 BSON 以检索值然后丢弃它.

这很有意义“如果”我可以即时编辑 BSON。除了允许我在构造 bsoncxx 文档/值/视图/元素的构建器之外,我在 bsoncxx 驱动程序文档中找不到任何内容。

举个例子,想象一下我有这样的东西

fruit["orange"];

其中fruitbsoncxx::document::element

我可以使用.get_xxx operators 之一来获取值。

我找不到类似的东西

fruit["orange"] = "ripe";

有没有办法做到这一点,或者构建器背后的想法是“只是”创建一个查询以提供给数据库?

【问题讨论】:

【参考方案1】:

有一个相同主题的问题,见here

所以,bsoncxx 对象似乎是不可变的,如果我们需要编辑它们,我们必须重新创建它们.. :(

我写了一个非常糟糕的解决方案,它从头开始重新创建文档

但我想这是一个解决方案。

std::string bsoncxx_string_viewToString(core::v1::string_view gotStringView) 
    std::stringstream convertingStream;
    convertingStream << gotStringView;
    return std::move(convertingStream.str());


std::string b_utf8ToString(bsoncxx::types::b_utf8 gotB_utf8) 
    return std::move(bsoncxx_string_viewToString(core::v1::string_view(gotB_utf8)));


template <typename T>
bsoncxx::document::value editBsoncxx(bsoncxx::document::view documentToEdit, std::string keyToEdit, T newValue, bool appendValueIfKeyNotExist = true) 
    auto doc = bsoncxx::builder::stream::document;
    std::string currentKey;
    for (auto i : documentToEdit) 
        currentKey = bsoncxx_string_viewToString(i.key());
        if (currentKey == keyToEdit) 
            doc << keyToEdit << newValue;
            appendValueIfKeyNotExist = false;
         else 
            doc << currentKey << i.get_value();
        
    
    if (appendValueIfKeyNotExist) // Maybe this would be better with documentToEdit.find(key), but I don't know how to check if iterator is past-the-end
        //If there is a way to check if bsoncxx contains key, we can achieve ~o(log(n)) [depending on 'find key' implementation] which is better than o(n)
        doc << keyToEdit << newValue;
    return doc.extract();

用法:

auto doc = document << "foo0" << "bar0" << "foo1" << 1  << "foo2" << 314 << finalize;
std::cout << bsoncxx::to_json(doc) << std::endl << std::endl;


doc = editBsoncxx<std::string> (doc.view(), "foo1", "edited"); //replace "foo1" with string "edited"
doc = editBsoncxx<int>(doc.view(), "baz_noappend", 123, false); //do nothing if key "baz_noappend" is not found. <- if key-existance algorythm will be applied, we'd spend about o(lob(n)) here, not o(n)
doc = editBsoncxx<int>(doc.view(), "baz_append", 123, true); //key will not be found => it'll be appended which is default behaviour
std::cout << bsoncxx::to_json(doc) << std::endl;

结果:

"foo0" : "bar0", "foo1" : 1, "foo2" : 314 "foo0" : "bar0", "foo1" : "edited", "foo2" : 314, "baz_append" : 123

所以,在你的情况下,你可以使用

fruit = editBsoncxx<std::string>(fruit.view(), "orange", "ripe");

但是,see already-mentioned related question 你说对了

构建器背后的想法是“只是”创建一个查询以提供给数据库?

我认为,解决方案是“不要编辑文档”。

你也可以编写类型转换器之类的东西,从 bsoncxx 到其他 json 存储格式(例如,rapidjson) 注意 value:"valid_json":bsoncxx::to_json 不会在 values 中的引号中添加反斜杠 => 可以进行注入。

【讨论】:

以上是关于您可以更改 bsoncxx 对象(文档/值/元素)吗?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法通过浏览器更改元素的相对位置值? [复制]

如何在 javascript 中更改 HTML 对象元素数据属性值

LitElement属性

在对象更改值时维护 TreeSet 排序

核心DOM-Document:文档对象

DOM:文档对象模型 --树模型 文档:标签文档,对象:文档中每个元素对象,模型:抽象化的东西