golang mgo 库的简单使用备忘

最近 golang 开发用到 mongodb,由于一些原因,我使用了 mgo 包进行开发。这篇文章记录一下 mgo 包的用法,一个比较浅的记录,做个备忘。

目前 mgo 已经不维护了,类似的包还有 官方七牛 (七牛的包基于mongo官方)的,都不错,可以试试。

mgo 的使用例子推荐这个网站——learningprogramming.net,写的挺好。

安装

go get gopkg.in/mgo.v2

使用

连接服务器

var mgoSession *mgo.Session
var mgoDatabase *mgo.Database

func GetMgo() *mgo.Session {
	return mgoSession
}

func GetDataBase() *mgo.Database {
	sessionCopy := mgoSession.Copy()
	mgoDatabase = sessionCopy.DB(setting.Config.Mongo.Database)
	return mgoDatabase
}

type Config struct {
	URL        string
	Database   string
	Collection string
	ReplicaSet string
}

func Setup(){
  mgoSession, err := mgo.Dial("username:password@10.19.0.57:7018,10.19.0.58:7018/dbname?replicaSet=replsetname")
  if err != nil {
    logrus.Error(err)
  }

  mgoSession.SetMode(mgo.Monotonic, true)
  mgo.SetDebug(true)
}

// 创建索引
func EnsureIndex(col string,keyArray []string) {
	mongoCol := GetDataBase().C(col)

	for _, key := range keyArray {
		err := mongoCol.EnsureIndex(
			mgo.Index{
				Key: []string{key},
				Background: true,
			})

		if err != nil {
			logrus.Errorln("create index error: ", err)
		}
	}
}

切换db

db := session.DB("test")

切换collection

c := db.C("users")

这样就能对mongo进行操作啦。

查找

查询可以用find,也可以用聚合管道(Aggregation Pipeline)。

find 就是普通的查询,聚合管道可以对集合中的文档进行变换和组合。

聚合管道以一个集合中的所有文档作为开始,然后这些文档从一个操作节点流向下一个节点 ,每个操作节点对文档做相应的操作。这些操作可能会创建新的文档或者过滤掉一些不符合条件的文档,在管道中可以对文档进行重复操作。

find

m := bson.M{
        "CurTimestamp": bson.M{
            "$gte": start,
            "$lte": end,
        },
        "Account":    account,
        "ToNodeType": "cloud",
    }

c.Find(m).Count()

pipeline

import "gopkg.in/mgo.v2/bson"

  match := bson.M{}

  if len(receivedData.Method) > 0 {
    matchIn := []interface{}{}
    for _, v := range receivedData.Method {
      matchIn = append(matchIn, v)
    }
    match["RequestMethod"] = bson.M{"$in":matchIn}
  }
  
  match["time"] = bson.M{"$lt": endedAt,"$gt": startedAt}
  

  pipeline := []bson.M{
    {"$match": match},
    {"$sort": bson.M{"time": -1}},
    {"$limit": limit},
    {"$skip": skip},
  }
  
  var xxxList []xxxItem
  c.Pipe(pipeline).All(&xxxList)

mapreduce

目前还没有使用mapreduce,以下例子来自《谈谈一些关于mgo的用法》

    m := new(mgo.MapReduce)
    m.Map = `function() { var date = new Date();
    date.setTime(this.CurTimestamp / 1000);
    var hour = date.getHours();
    if((hour >= 6) && (hour <= 11)) {
        result.morning++;
    }else if((hour >= 12) && (hour <= 18)){
        result.afternoon ++;
    }else if((hour >= 19) && (hour <= 23)) {
        result.night ++;
    }else{
        result.am ++;
    }
    emit(this.Account, {});}`
    m.Reduce = `function() {return result;}`
    m.Scope = bson.M{
        "result": bson.M{
            "morning":   0,
            "afternoon": 0,
            "night":     0,
            "am":        0,
        },
    }
    var value []timeResult
    c.Find().MapReduce(m, &value)

update

import "gopkg.in/mgo.v2/bson"

err = c.UpdateId(bson.ObjectIdHex(xxx.ID.Hex()), bson.M{"$set": bson.M{"ClientUsername": username,}})

err := c.Update(bson.M{"wsid": wsid}, bson.M{"$set": bson.M{"endtime": time.Now(),}})

修改字段的值($set)

c.Update(bson.M{"_id": bson.ObjectIdHex("5204af979955496907000001")}, bson.M{"$set": bson.M{ "name": "Jimmy Gu", "age": 34, }})

字段增加值inc($inc)

c.Update(bson.M{"_id": bson.ObjectIdHex("5204af979955496907000001")}, bson.M{"$inc": bson.M{ "age": -1, }})

从数组中增加一个元素push($push)

c.Update(bson.M{"_id": bson.ObjectIdHex("5204af979955496907000001")}, bson.M{"$push": bson.M{ "interests": "Golang", }})

从数组中删除一个元素pull($pull)

c.Update(bson.M{"_id": bson.ObjectIdHex("5204af979955496907000001")}, bson.M{"$pull": bson.M{ "interests": "Golang", }})

create

  create := XxxStruct{}
  create.Time = time.Now()
  create.Wsid = wsid
  c.Insert(create)

remove

c.Remove(bson.M{"name": "Jimmy Kuu"})

条件匹配

=($eq)

c.Find(bson.M{"name": "Jimmy Kuu"}).All(&users)

!=($ne)

c.Find(bson.M{"name": bson.M{"$ne": "Jimmy Kuu"}}).All(&users)

>($gt)

c.Find(bson.M{"age": bson.M{"$gt": 32}}).All(&users)

<($lt)

c.Find(bson.M{"age": bson.M{"$lt": 32}}).All(&users)

>=($gte)

c.Find(bson.M{"age": bson.M{"$gte": 33}}).All(&users)

<=($lte)

c.Find(bson.M{"age": bson.M{"$lte": 31}}).All(&users)

in($in)

c.Find(bson.M{"name": bson.M{"$in": []string{"Jimmy Kuu", "Tracy Yu"}}}).All(&users)

$nin 不在集合内

iter = c.Find(bson.M{"city": bson.M{"$nin": []string{"Shanghai", "Hangzhou"}}}).Iter()

$exists 是否包含键

iter = c.Find(bson.M{"city": bson.M{"$exists": true}}).Iter()

键值为null(键存在,键值为null)

iter = c.Find(bson.M{"city": bson.M{"$in": []interface{}{nil}, "$exists": true}}).Iter()

and($and)

c.Find(bson.M{"name": "Jimmy Kuu", "age": 33}).All(&users)

or($or)

c.Find(bson.M{"$or": []bson.M{bson.M{"name": "Jimmy Kuu"}, bson.M{"age": 31}}}).All(&users)

结果操作

排序 Sort

//按age升序,如果要降序Sort("-age")
iter = c.Find(bson.M{"age": bson.M{"$gte": 33}}).Sort("age").Iter()

限定结果数量 Limit

//使用Limit限定只去5条记录
iter = c.Find(bson.M{"age": bson.M{"$gte": 20}}).Sort("age").Limit(5).Iter()

跳过指定数量的记录 Skip

//跳过两条记录,取接下来的5条记录
iter = c.Find(bson.M{"age": bson.M{"$gte": 20}}).Sort("age").Skip(2).Limit(5).Iter()

计算记录的条数 Count

recordsCount, err := c.Find(bson.M{"age": bson.M{"$gte": 20}}).Count()

参考资料


windows 通过命令行设置应用程序的窗口位置 golang 解析 map[string]interface{} 和 json 到 struct