MongoDB C ++更新数组中的元素

时间:2018-04-07 13:39:06

标签: c++ mongodb mongodb-query mongo-cxx-driver

我是MongoDB和C ++的新手。 我的问题:我想从我的数据库集合中更新JSON-Document:

{
    "_id" : ObjectId("5ac4beacc0e2a512e6377d43"),
    "docID" : "SL/UO4ZJgdUxcRLKxXDWMg==",
    "docVersion" : "DA3EF8047AD0F[…]77C6F9286488CEE6a",
    "userID" : "bob@nds-local",
    "parts" : [
        {
            "partID" : "u2v[…]0KG7R",
            "partVersion" : "",
            "partKey" : "",
            "docPosition" : 0,
            "counter" : 0,
            "users" : {
                "everyone" : [ 1, 0, 0, 0, 0, 0, 0, 0, 0 ]
            }
        },
        {
            "partID" : "AZ3[…]1Odeku",
            "partVersion" : "",
            "partKey" : "",
            "docPosition" : 0,
            "counter" : 0,
            "users" : {
            }
        }
    ]
}

首先,我想从我的数据库中获取此文档。因此我使用这个小代码:

bsoncxx::stdx::optional<bsoncxx::document::value> resultDocument =
            collection.find_one(document{} << "docID" << docID << finalize);

操作元素的一种方法是使用update-function:

collection.update_one(document{} << "docID" << docID
                                     << "docVersion" << docVersion
                                     << finalize,
                          document{} << "$set" << open_document <<
                                     "userID" << "oscar@nds-local" << close_document << finalize);

但我不想操纵用户ID! 我想通过键&#34;部件&#34;来访问数组。 (取决于&#34; partID = u2v [...] 0KG7R&#34;)。 之后,我想更新/替换此数组的子元素partVersion,partKey和docPosition。 (1)我该怎么做?

此外,我想访问子阵列&#34;用户&#34;并添加键,删除键和操纵一个特殊用户的数组。 (2)我怎么能意识到这一点?

如果有人可以为我的问题(1)举个例子,那就太好了。我希望(1)的这个答案能给我一个如何处理问题(2)......

的线索

1 个答案:

答案 0 :(得分:0)

不需要从数据库中检索文档,您可以一口气更新文档。

您还需要使用dot notationpartID在查询中添加parts.partID字段,以在数组中找到一个匹配的对象。

要更新您请求的字段(1)并在users中添加新键(2),您需要使用positional $ operator,因为它将允许访问查询匹配的元素。< / p>

它看起来像这样:

db["docs"].update_one(
    make_document(
        kvp("docID", docID),
        kvp("parts.partID", partID)
    ),
    make_document(
        kvp("$set", make_document(
                        kvp("parts.$.partKey", newPartKey),
                        kvp("parts.$.partVersion", newPartVersion),
                        kvp("parts.$.docPosition", newDocPosition),
                        kvp("parts.$.users." + newUser, make_array(1,2,3,4,5))
                    )
        )
    )
);

kvp("parts.$.users." + newUser, make_array(1,2,3,4,5))将在users内使用变量newUser的值创建一个键,并将包含数组[1,2,3,4,5]

使用$unset运算符可以类似的方式删除用户(2):

db["docs"].update_one(
    make_document(
        kvp("docID", docID),
        kvp("parts.partID", partID)
    ),
    make_document(
        kvp("$unset", make_document(kvp("parts.$.users." + userToDelete, "")))
    )
);

如何操纵一个特定用户(2)的数组将取决于您计划对其进行精确更新的方式/方式,但是为此您可以使用array update operators


以下代码段:

  1. 首先,它更新partKeypartVersiondocPosition字段,并在users字段中为 partID:"AZ3[...]1Odeku"部分
  2. 第二,它删除了之前添加的用户

请注意,我已经从文档数据中将省略号替换为三个点...,因为这导致mongocxx驱动程序即使使用省略号也从未找到任何匹配项在查询中使用(在mongo shell中运行良好)

#include <iostream>

#include <bsoncxx/json.hpp>

#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
#include <mongocxx/uri.hpp>

using bsoncxx::builder::basic::kvp;
using bsoncxx::builder::basic::make_array;
using bsoncxx::builder::basic::make_document;

void updatePartAndAddNewUser(const mongocxx::client& client,
                             const std::string& docID,
                             const std::string& partID,
                             const std::string& newPartKey,
                             const std::string& newPartVersion,
                             int newDocPosition,
                             const std::string& newUser)
{
    mongocxx::database db = client["stack"];

    db["docs"].update_one(
        make_document(
            kvp("docID", docID),
            kvp("parts.partID", partID)
        ),
        make_document(
            kvp("$set", make_document(
                            kvp("parts.$.partKey", newPartKey),
                            kvp("parts.$.partVersion", newPartVersion),
                            kvp("parts.$.docPosition", newDocPosition),
                            kvp("parts.$.users." + newUser, make_array(1,2,3,4,5))
                        )
            )
        )
    );
}

void removeUserFromPart(const mongocxx::client& client,
                        const std::string& docID,
                        const std::string& partID,
                        const std::string& userToDelete)
{
    mongocxx::database db = client["stack"];

    db["docs"].update_one(
        make_document(
            kvp("docID", docID),
            kvp("parts.partID", partID)
        ),
        make_document(
            kvp("$unset", make_document(kvp("parts.$.users." + userToDelete, "")))
        )
    );
}

int main(int, char**)
{
    std::cout << "Start program" << std::endl;

    mongocxx::instance instance{};
    mongocxx::client client{ mongocxx::uri{} };

    updatePartAndAddNewUser(client,
                            "SL/UO4ZJgdUxcRLKxXDWMg==",
                            "AZ3[...]1Odeku",
                            "newPartKey",
                            "newPartVersion1",
                            1,
                            "nobody");

    std::cout << "Part has been modified, press any key to remove a user..."; 
    std::cin.ignore();

    removeUserFromPart(client,
                       "SL/UO4ZJgdUxcRLKxXDWMg==",
                       "AZ3[...]1Odeku",
                       "nobody");

    std::cout << "End program" << std::endl;
}

执行updatePartAndAddNewUser(...)后生成此文档:

{
        "_id" : ObjectId("5ac4beacc0e2a512e6377d43"),
        "docID" : "SL/UO4ZJgdUxcRLKxXDWMg==",
        "docVersion" : "DA3EF8047AD0F[...]77C6F9286488CEE6a",
        "userID" : "bob@nds-local",
        "parts" : [
                {
                        "partID" : "u2v[...]0KG7R",
                        "partVersion" : "",
                        "partKey" : "",
                        "docPosition" : 0,
                        "counter" : 0,
                        "users" : {
                                "everyone" : [1,0,0,0,0,0,0,0,0]
                        }
                },
                {
                        "partID" : "AZ3[...]1Odeku",
                        "partVersion" : "newPartVersion1",
                        "partKey" : "newPartKey",
                        "docPosition" : 1,
                        "counter" : 0,
                        "users" : {
                                "nobody" : [1,2,3,4,5]
                        }
                }
        ]
}

执行removeUserFromPart(...)后,nobody用户就走了:

{
        "_id" : ObjectId("5ac4beacc0e2a512e6377d43"),
        "docID" : "SL/UO4ZJgdUxcRLKxXDWMg==",
        "docVersion" : "DA3EF8047AD0F[...]77C6F9286488CEE6a",
        "userID" : "bob@nds-local",
        "parts" : [
                {
                        "partID" : "u2v[...]0KG7R",
                        "partVersion" : "",
                        "partKey" : "",
                        "docPosition" : 0,
                        "counter" : 0,
                        "users" : {
                                "everyone" : [1,0,0,0,0,0,0,0,0]
                        }
                },
                {
                        "partID" : "AZ3[...]1Odeku",
                        "partVersion" : "newPartVersion1",
                        "partKey" : "newPartKey",
                        "docPosition" : 1,
                        "counter" : 0,
                        "users" : {

                        }
                }
        ]
}