mongo-driver(Golang)条件转化对应关系,函数,聚合使用group,match,sample等

代码例子在最下面,不看介绍直接下滑

以下所有例子中结构定义如下:

type User struct {
    Id_ bson.ObjectId `bson:"_id"`
    Name string `bson:"name"`
    Age int `bson:"age"`
    JoinedAt time.Time `bson:"joined_at"`
    Interests []string `bson:"interests"
}

1、查询

通过func (c *Collection) Find(query interface{}) *Query来进行查询,返回的Query struct可以有附加各种条件来进行过滤。

通过Query.All()可以获得所有结果,通过Query.One()可以获得一个结果,注意如果没有数据或者数量超过一个,One()会报错。

条件用bson.M{key: value},注意key必须用MongoDB中的字段名,而不是struct的字段名。

1.1、连接并查询(下面所有集合用c代替)

ctx, canf := context.WithTimeout(context.Background(), 10*time.Second)
// defer canf()
client, err := mongo.Connect(ctx, options.Client().ApplyURI(driver))
if err != nil {
    return nil, err
}
c:= client.Database(database).Collection(collect)
c.Find(ctx, where, opts...)

上面代码可以把所有Users都查出来:

1.2、根据ObjectId查询,单条语句

c.FindOne(m.Ctx, where, opts...).Decode(&result)

注意这里没有处理err。注意自己的查询ERR。

关键是这个

关键是这个

关键是这个

1.3、单条件查询

等于($eq)

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

不等于($ne)

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

大于($gt)

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

小于($lt)

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

大于等于($gte)

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

小于等于($lte)

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

in($in)

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

no in($nin)

同$in,

是否包含这个键($exists)

c.Find(bson.M{"name": bson.M{"$exists": true}})

查询键值为null的字段

c.Find(bson.M{"name": bson.M{"$in":[]interface{}{null}, "$exists": true}})

模糊查询($regex)

c.Find(bson.M{"name": bson.M{"$regex": "^[0-9]+"}})
c.Find(bson.M{"name": bson.M{"$regex": primitive.Regex{Pattern: "[aa]+", Options: "im"}}})//查出包含aa的,后面的是正则表达式

$size

查询键值为长度是size的数组

c.Find(bson.M{"Interests": bson.M{"$size": 3}})

上面就是查询Interests数组长度为3的所有人

$all

查询数组中包含所有值得匹配(不分顺序,只看包含与否)

c.Find(bson.M{"Interests": bson.M{"$all": []string{"11","22","33"}}})

上面就是查询Interests中包含11,22,33的所有人

如果数组只有一项内容

c.Find(bson.M{"Interests": bson.M{"$all": []string{"11"}}})
c.Find(bson.M{"Interests": "11"})

以上结果一致

key.index

如果要查询数组指定位置

c.Find(bson.M{"Interests.2": "33"})

以上就是查询Interests的第二个元素为"33"的所有人

1.4、多条件查询

and($and)

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

or($or)

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

2、修改
通过func (*Collection) Update来进行修改操作。

func (c *Collection) Update(selector interface{}, change interface{}) error

注意修改单个或多个字段需要通过$set操作符号,否则集合会被替换。

2.1、($set)
修改字段的值

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

2.2、inc($inc)
字段增加值

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

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

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

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

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

2.5、删除

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

这里也支持多条件,参考多条件查询。

例子一

package main

import (
    "context"
    "log"

    "go.mongodb.org/mongo-driver/mongo/readpref"

    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    "gopkg.in/mgo.v2/bson"
)

func main() {
    ctx, canf := context.WithCancel(context.Background())
    defer canf()
    client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017"))
    if err != nil {
        log.Println("err:", err)
        return
    }
    if err := client.Ping(ctx, readpref.Primary()); err != nil {
        log.Println("err:", err)
        return
    }
    clo := client.Database("stb")
    // insert(ctx, clo)
    // update(ctx, clo)
    delete(ctx, clo)
    selectOne(ctx, clo)

}

func insert(ctx context.Context, db *mongo.Database) {
    data := bson.M{"room_id": "123", "host_name": "shitingbao", "room_name": "mantou", "room_type": "love", "common": "loss"}
    _, err := db.Collection("chatroom").InsertOne(ctx, data)
    if err != nil {
        log.Println("err:", err)
        return
    }
}

func update(ctx context.Context, db *mongo.Database) {
    _, err := db.Collection("chatroom").UpdateOne(ctx, bson.M{"room_id": "123"}, bson.M{"$set": bson.M{"host_name": "mantou"}})
    if err != nil {
        log.Println("err:", err)
        return
    }

}

func delete(ctx context.Context, db *mongo.Database) {
    if err := db.Collection("chatroom").FindOneAndDelete(ctx, bson.M{"room_id": "123"}).Err(); err != nil {
        log.Println("err:", err)
        return
    }
}

func selectOne(ctx context.Context, db *mongo.Database) {
    var result bson.M
    if err := db.Collection("chatroom").FindOne(ctx, bson.M{"room_id": "123"}).Decode(&result); err != nil {
        log.Println("err:", err)
        return
    }
    log.Println(result)
}

例子二,带函数使用的例子(limit,skip等)

这里注意的是,https://github.com/mongodb/mongo-go-driver 中没有直接使用的该方法,因为他已经从中间剥离出来了,在该包下面的options包下面重新定义一个结构,进行设置,或者调用对应方法操作。
一下面例子为例,Find方法反馈一个FindOptions结构体,可以从源码中了解到,所有的属性都有,当然你可以自己定义一个,不过这个类型转化太麻烦,就直接使用他包装好的函数,比如这里设置跳过数据的skip函数,跳过两条数据,其他的函数同理使用。

//查询name为aa的第三条数据开始的数据
func selectWhere(ctx context.Context, db *mongo.Database) {
    var result []bson.M
    cur, err := db.Collection("collect").Find(ctx, bson.M{"name":"aa"}, options.Find().SetSkip(2))
    if err != nil {
        return
    }
    defer cur.Close(ctx)

    for cur.Next(ctx) {
        var res bson.M
        if err := cur.Decode(&res); err != nil {
            return
        }
        result = append(result, res)
    }
    if err := cur.Err(); err != nil {
        return
    }
    log.Println(result)
}

聚合函数,注意pipeline 内容,其他都不重要

func OpenMongoDb(client *mongo.Client, driver, database,collection string) error {
    ctx := context.TODO()
    clo := client.Database(database).Collection(collection )
    pipeline := []bson.M{//注意这个,这是个数组,对应就行
        {
             //第一位必须要是累加器对象,就是这个id,对应你要聚合的实际列名,这里是name
            //第二位是列的名称count,自己取一个名字类似于sql中as后面的名称,里面那个是固定格式
          //对应的sql就是,select name,sum(name) as count from table group by name
            "$group": bson.M{"_id": "$name", "count": bson.M{"$sum": 1}},
        },
    }
    cur, err := clo.Aggregate(ctx, pipeline)
    if err != nil {
        return err
    }

    var result []bson.M
    defer cur.Close(ctx)
    for cur.Next(ctx) {
        var res bson.M
        if err := cur.Decode(&res); err != nil {
            return err
        }
        result = append(result, res)
    }
    if err := cur.Err(); err != nil {
        return err
    }
    log.Println(result)
    return nil
}

上述的聚合,对于多列就是,相当于group by name,age

    pipeline := []bson.M{
        {
            "$group": bson.M{"_id": bson.M{"name": "$name", "age": "$age"}, "count": bson.M{"$sum": 1}},
        },
    }

//对应mongodb语句就是
db.chatroom.aggregate([{$group:{_id:{"name":"$name","age":"$age"},num_tutorial:{$sum:1}}}])

再举个例子

db.chatroom.aggregate([{$match:{name:{$nin:["aa","bb"]}}},{$sample:{size:3}}])

对应的就是

    where := []bson.M{
        {
            "$match": bson.M{
                "name": bson.M{
                    "$nin": pm.RoomID},
            },
        },
        {
            "$sample": bson.M{
                "size": 3,
            },
        },
    }
    cur, err := core.Mdb.CollectionDB.Collection("chatroom").Aggregate(core.Mdb.Ctx, where)
    if err != nil {
        return err
    }
    var result []bson.M
    defer cur.Close(core.Mdb.Ctx)
    for cur.Next(core.Mdb.Ctx) {
        var res bson.M
        if err := cur.Decode(&res); err != nil {
            return err
        }
        result = append(result, res)
    }
    if err := cur.Err(); err != nil {
        return err
    }
    log.Println(result)

你可能感兴趣的:(mongo-driver(Golang)条件转化对应关系,函数,聚合使用group,match,sample等)