mongodb学习笔记–C++操作mongodb

mongodb学习笔记–C++操作mongodb

  在学习mongodb过程当中,必须学习的就是用C++(Java、PHP、C#等)操作mongodb,这里讲述C++操作mongodb,在官方提供的mongo-cxx-driver驱动中有相关的操作例子,可以结合例子学习,目录是mongo-cxx-driver-legacy-1.0.0-rc0\src\mongo\client\examples,这里针对几个重要的点讲述。

1. C++连接mongodb

(1)有无密码都适用

mongo::client::GlobalInstance instance;
if (!instance.initialized()) {
    std::cout << "failed to initialize the client driver: " << instance.status() << std::endl;
    return EXIT_FAILURE;
}

std::string uri = "mongodb://username:password@127.0.0.1:27017";
std::string errmsg;

ConnectionString cs = ConnectionString::parse(uri, errmsg);

if (!cs.isValid()) {
    std::cout << "Error parsing connection string " << uri << ": " << errmsg << std::endl;
    return EXIT_FAILURE;
}

boost::scoped_ptr<DBClientBase> conn(cs.connect(errmsg));
if (!conn) {
    cout << "couldn't connect : " << errmsg << endl;
    return EXIT_FAILURE;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

  这种方式有密码和无密码的情况都适用,"username"为登录名,"password"为登录密码;无密码时去掉"username:password@"即可连接,这样连接方式比较常用。

(2)常规连接操作(不带密码连接)

mongo::DBClientConnection conn; 
mongo::Status status = mongo::client::initialize();
if (!status.isOK()) {
    MongoException m(-1, "failed to initialize the client driver: " + status.toString());
    return -1;
}
string url = "localhost:27017";
if (!conn.connect(url, errmsg)) {
    MongoException m(0, "couldn’t connect : " + errmsg);
    return -1;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

通过这种方式可建立与mongodb的连接,但是是未带权限的连接。

(3)带密码连接

conn.auth( "admin" , "username" , "password" , errmsg );
  • 1

  其中"admin"为验证用户的所在数据库,一般在"test.system.users""admin.system.users"表中,所以填库名"test""admin""username"为登录名,"password"为登录密码。 
或者下面的auth方式也可以:

conn.auth(BSON(
    "user" << "root" << "db" << "admin" <<
    "pwd" << "password" << "mechanism" << "DEFAULT"
));
  • 1
  • 2
  • 3
  • 4

根据mongodb的设置更改传递给函数conn.auth的参数值。

2. C++查询数据

const char* ns = "test.first";
conn->findOne(ns, BSONObj()); //查询一条数据
conn->findOne(ns, BSONObjBuilder().append("name", "joe").obj()); //条件查询
  • 1
  • 2
  • 3

3. C++插入数据

const char* ns = "test.first";
conn->insert(ns, BSON("name" << "joe" 
                      << "pwd" << "123456" 
                      << "age" << 20));
  • 1
  • 2
  • 3
  • 4

4. C++删除数据

const char* ns = "test.first";
conn->remove(ns, BSONObj()); //删除所有
conn->remove(ns, BSONObjBuilder().append("name", "joe").obj()); //删除指定文档
  • 1
  • 2
  • 3

5. C++更新数据

(1) 在原数据基础上增加属性

const char* ns = "test.first";
BSONObj res = conn->findOne(ns, BSONObjBuilder().append("name", "joe").obj());
BSONObj after = BSONObjBuilder().appendElements(res).append("name2", "h").obj();
conn->update(ns, BSONObjBuilder().append("name", "jeo2").obj(), after); //在原数据上增加属性
  • 1
  • 2
  • 3
  • 4

这种update方式只是在原数据基础上增加属性,并不会改变指定属性值。 
(2) 更改指定的某个属性值 
想要update指定属性的值,需要用到”$set”指令,如下代码所示:

BSONObj res = conn->findOne(ns, BSONObjBuilder().append("name", "joe").obj());
//更改指定的某个属性值
conn->update("test.first", res, BSON("$set" << BSON("age" << 11)));
  • 1
  • 2
  • 3

主要想强调下update更改指定的某个属性值的方式,比较常用。

6. C++操作例子

(1) simple_client_test.cpp

/*
#if defined(_WIN32)
#include <winsock2.h>
#include <windows.h>
#endif*/
//g++ simple_client_test.cpp -pthread -lmongoclient -lboost_thread -lboost_system -lboost_regex -o simple_client_test
#include "mongo/client/dbclient.h"  // the mongo c++ driver

#include <iostream>

#ifndef verify
#define verify(x) MONGO_verify(x)
#endif

using namespace std;
using namespace mongo;
//using mongo::BSONObj;
//using mongo::BSONObjBuilder;

int main(int argc, char* argv[]) {
    if (argc > 2) {
        std::cout << "usage: " << argv[0] << " [MONGODB_URI]" << std::endl;
        return EXIT_FAILURE;
    }

    mongo::client::GlobalInstance instance;
    if (!instance.initialized()) {
        std::cout << "failed to initialize the client driver: " << instance.status() << std::endl;
        return EXIT_FAILURE;
    }

    std::string uri = argc == 2 ? argv[1] : "mongodb://127.0.0.1:27017";
    std::string errmsg;

    ConnectionString cs = ConnectionString::parse(uri, errmsg);

    if (!cs.isValid()) {
        std::cout << "Error parsing connection string " << uri << ": " << errmsg << std::endl;
        return EXIT_FAILURE;
    }

    boost::scoped_ptr<DBClientBase> conn(cs.connect(errmsg));
    if (!conn) {
        cout << "couldn't connect : " << errmsg << endl;
        return EXIT_FAILURE;
    }

    const char* ns = "test.first";

    conn->dropCollection(ns);

    //clean up old data from any previous tesets
    conn->remove(ns, BSONObj());
    verify(conn->findOne(ns, BSONObj()).isEmpty()); //verify逻辑表达式,判断是否还存在test.first,是否clenn up成功

    //test insert
    cout << "(1) test insert----" << endl;
    conn->insert(ns, 
                 BSON("name" << "joe" 
                      << "pwd" << "123456" 
                      << "age" << 20));
    verify(!conn->findOne(ns, BSONObj()).isEmpty());     //判断是否添加成功
    cout << "insert data : " << conn->findOne(ns, BSONObj()) << endl;
    cout << "insert success!" << endl;

    // test remove
    cout << "(2) test remove----" << endl;
    conn->remove(ns, BSONObj());
    verify(conn->findOne(ns, BSONObj()).isEmpty());
    cout << "remove success!" << endl;

    // insert, findOne testing
    conn->insert(ns, 
                 BSON("name" << "joe" 
                      << "pwd" << "234567" 
                      << "age" << 21));
    {
        BSONObj res = conn->findOne(ns, BSONObj());
        verify(strstr(res.getStringField("name"), "joe"));
        verify(!strstr(res.getStringField("name2"), "joe"));
        verify(21 == res.getIntField("age"));
    }
    cout << "insert data : " << conn->findOne(ns, BSONObj()) <<endl;

    // test update
    {
        BSONObj res = conn->findOne(ns, BSONObjBuilder().append("name", "joe").obj());
        verify(!strstr(res.getStringField("name2"), "jeo"));

        BSONObj after = BSONObjBuilder().appendElements(res).append("name2", "w").obj();
        cout << "(3) test update name joe add name2 name3----" << endl;
        //upsert type1 update method
        conn->update(ns, BSONObjBuilder().append("name", "joe").obj(), after);
        //res = conn->findOne(ns, BSONObjBuilder().append("name2", "w").obj());
        verify(!strstr(res.getStringField("name2"), "joe"));
        verify(conn->findOne(ns, BSONObjBuilder().append("name", "joe2").obj()).isEmpty());
        //cout << " update1 data: " << conn->findOne(ns, BSONObj()) << endl;
        cout << " update1 data : " << conn->findOne(ns, Query("{name2:'w'}")) << endl;

        //upsert type2 update method 更改指定的某个属性值 
        const string TEST_NS = "test.first";
        conn->update("test.first", res, BSON("$set" << BSON("age" << 11)));
        cout << " update2 data : " << conn->findOne(ns, BSONObj()) << endl;
        res = conn->findOne(ns, BSONObjBuilder().append("name", "joe").obj());

        //upsert type3 update method
        try
        {
            after = BSONObjBuilder().appendElements(res).append("name3", "h").obj();
            conn->update(ns, BSONObjBuilder().append("name", "joe").obj(), after);
        }
        catch (OperationException&)
        {
            cout << " update error: " << conn->getLastErrorDetailed().toString() << endl;
        }
        verify(!conn->findOne(ns, BSONObjBuilder().append("name", "joe").obj()).isEmpty());
        //cout << " update3 data: " << conn->findOne(ns, BSONObj()) << endl;
        cout << " update3 data : " << conn->findOne(ns, Query("{name3:'h'}")) << endl;

        cout << "(4) test query-----" << "\n query data : " 
            << conn->findOne(ns, BSONObjBuilder().append("name", "joe").obj()) << endl;
        cout << " Query data : " << conn->findOne(ns, Query("{name:'joe'}")) << endl;
    }

    return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127

(2) makefile文件

CC = g++
TEST = simple_client_test

$(TEST):
    $(CC) $@.cpp -pthread -lmongoclient -lboost_thread -lboost_system -lboost_regex -o $@
    ./$(TEST)
    rm -f $(TEST)
run:
    ./$(TEST)

clean:
    rm -f $(TEST)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值