mongodb對外接口或驅動:https://docs.mongodb.com/ecosystem/drivers/,包含C,C++,Go,Python等。
C驅動
mongodb的C驅動,即libmongoc,是一個用於開發mongodb的C庫。依賴libbson,libbson用於生成和解析BSON documents。
mongoDB C Driver官網:http://mongoc.org/libmongoc/current/index.html。
安裝
下載最新的1.14.1tar包安裝(mongo-c-driver-1.14.1.tar.gz)。
sudo apt-get install cmake libssl-dev libsasl2-dev
$ wget https://github.com/mongodb/mongo-c-driver/releases/download/x.y.z/mongo-c-driver-x.y.z.tar.gz
$ tar xzf mongo-c-driver-x.y.z.tar.gz
$ cd mongo-c-driver-x.y.z
$ mkdir cmake-build
$ cd cmake-build
$ cmake -DENABLE_AUTOMATIC_INIT_AND_CLEANUP=OFF ..
$ make
$ sudo make install
$ sudo make uninstall
編譯鏈接
gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-1.0)
gcc -o hello_mongoc hello_mongoc.c $(pkg-config --libs --cflags libmongoc-static-1.0)
$ gcc -o hello_mongoc hello_mongoc.c \
-I/usr/local/include/libbson-1.0 -I/usr/local/include/libmongoc-1.0 \
-lmongoc-1.0 -lbson-1.0
$ ./hello_mongoc
增刪改查
Go驅動
mongodb的Go驅動很多,官方提供的驅動:https://godoc.org/go.mongodb.org/mongo-driver/mongo 或 https://docs.mongodb.com/ecosystem/drivers/go/
edgex中用到的是mgo(社區版):https://github.com/globalsign/mgo或https://godoc.org/github.com/globalsign/mgo。其clone於gopkg.in/mgo.v2(不再更新)。
mgo的核心基於session,Dail()基於url建立連接用於后續的查詢:
session, err := mgo.Dial(url) c := session.DB(database).C(collection) err := c.Find(query).One(&result)
函數原型:
func (c *Collection) Find(query interface{}) *Query
Find prepares a query using the provided document. The document may be a map or a struct value capable of being marshalled with bson.
The map may be a generic one using interface{} for its key and/or values, such as bson.M, or it may be a properly typed map.
Providing nil as the document is equivalent to providing an empty document such as bson.M{}.
func (q *Query) One(result interface{}) (err error)
One executes the query and unmarshals the first obtained document into the result argument.
The result must be a struct or map value capable of being unmarshalled into by gobson.
This function blocks until either a result is available or an error happens. For example:
err := collection.Find(bson.M{"a": 1}).One(&result)
查詢語句語法參考:https://docs.mongodb.com/manual/tutorial/query-documents/
package main import ( "fmt" "gopkg.in/mgo.v2" "gopkg.in/mgo.v2/bson" ) type Person struct { Name string Phone string } func main() { session, err := mgo.Dial("127.0.0.1") if err != nil { panic(err) } defer session.Close() session.SetMode(mgo.Monotonic, true) c := session.DB("test").C("people") err = c.Insert(&Person{"Ale", "+55 53 8116 9639"}, &Person{"Cla", "+55 53 8402 8510"}) if err != nil { panic(err) } result := Person{} err = c.Find(bson.M{"name": "Ale"}).One(&result) if err != nil { panic(err) } fmt.Println("Phone:", result.Phone) }
mgo中session
Strong
session 的讀寫一直向主服務器發起並使用一個唯一的連接,因此所有的讀寫操作完全的一致。
Monotonic
session 的讀操作開始是向其他服務器發起(且通過一個唯一的連接),只要出現了一次寫操作,session 的連接就會切換至主服務器。
由此可見此模式下,能夠分散一些讀操作到其他服務器,但是讀操作不一定能夠獲得最新的數據。
Eventual
session 的讀操作會向任意的其他服務器發起,多次讀操作並不一定使用相同的連接,也就是讀操作不一定有序。session 的寫操作總是向主服務器發起,但是可能使用不同的連接,也就是寫操作也不一定有序。
mgo中全局session有兩個問題:
1)效率問題。全局session只有一個socket,不支持並發。
2)mgo.Session緩存的一主一從連接,實例本身不負責維護,需要應用維護。也就是說,當slaveSocket
,masterSocket
任意其一,連接斷開,Session自己不會重置緩存,該Session的使用者如果不主動重置緩存,調用者得到的將永遠是EOF
。這種情況在主從切換時就會發生,在網絡抖動時也會發生。這是致命的,連接斷開或MongoDB重啟時永遠連接不上,報EOF。
解決全局session問題的方法有兩個,采用SessionCopy機制或Eventual模式。Copy機制時,每次查詢都用一個session,查詢完后關閉session,讓mgo維護session復用。
參考:
https://cardinfolink.github.io/2017/05/17/mgo-session/ mgo的session與連接池
https://www.bbsmax.com/A/rV574pAXdP/ golang mgo的mongo連接池設置:必須手動加上maxPoolSize
mgo中日志實現
// 實現 mongo.Logger 的接口 type MongoLog struct { } func (MongoLog)Output(calldepth int, s string) error { log.SetFlags(log.Lshortfile) return log.Output(calldepth,s) } mgo.SetDebug(true) // 設置DEBUG模式 mgo.SetLogger(new(MongoLog)) // 設置日志.
func ConfigCollection() *mgo.Collection {
if configCollection != nil {
return configCollection
}
db := dbConfig()
url := db.Host + ":" + strconv.Itoa(db.Port)
log.Printf("mongo connect info(url:%s, dbName:%s, collection:%s)\n", url, db.DB, db.Collection)
session, err := mgo.Dial(url)
if err != nil {
log.Fatalf("Connect mongo failed: %v \n", err)
}
// session.SetMode(mgo.Monotonic, true
// mgo.SetDebug(true)
// mgo.SetLogger(new(mongoLog))
session.SetMode(mgo.Eventual, true)
session.SetSocketTimeout(2 * time.Second)
session.SetSyncTimeout(2 * time.Second)
configCollection = session.DB(db.DB).C(db.Collection)
return configCollection
}
要使日志使能,必須SetLogger()。
參考: