golang mongo 查询总结

golang 使用 “gopkg.in/mgo.v2” 查询mongo总结。mongo的增加,更新和删除操作比较简单,查询操作相对灵活复杂一些,下面对golang 查询 mongo 做个总结。完整代码上传到了 https://gitee.com/truthalone/go-mongo.git 。

1.连接 mongo

//mongo.go

package main

import (
    "errors"
    "time"

    "gopkg.in/mgo.v2"
)

// 连接mongodb数据库
var (
    mongodbAddr     string = "" //mongodb数据库地址
    mongodbName     string = "" //mongodb数据名称
    mongodbUser     string = "" //mongodb用户名
    mongodbPassword string = "" //mongodb密码
)

var (
    session *mgo.Session
)

func init() {
    mongodbAddr = "127.0.0.1"
    mongodbName = "demo"
    mongodbUser = "root"
    mongodbPassword = "ming"
}

func GetMongoSession() *mgo.Session {
    if session == nil {
        var err error

        if mongodbUser == "" || mongodbPassword == "" {
            session, err = mgo.Dial(mongodbAddr)
        } else {
            dialInfo := &mgo.DialInfo{
                Addrs:     []string{mongodbAddr},
                Direct:    false,
                Timeout:   time.Second * 30,
                Database:  mongodbName,
                Source:    "admin",
                Username:  mongodbUser,
                Password:  mongodbPassword,
                PoolLimit: 4096, // Session.SetPoolLimit
            }

            session, err = mgo.DialWithInfo(dialInfo)
        }

        if err != nil {
            return nil
        }
    }

    return session.Clone()
}

func WithMongoCollection(collectionName string, s func(*mgo.Collection) error) error {
    session := GetMongoSession()
    if session == nil {
        return errors.New("获取mongodb连接失败")
    }
    defer session.Close()

    c := session.DB(mongodbName).C(collectionName)
    return s(c)
}

2.插入数据

插入的数据包含子文档和数组数据,平时比较复杂的查询也是子文档查询和数组查询

//book.go

//图书
type Book struct {
    Id      bson.ObjectId `bson:"_id"`    //主键
    Name    string        `bson:"name"`   //图书名称
    Price   float32       `bson:"price"`  //价格
    Authors []Author      `bson:"author"` //作者
    Tags    []string      `bson:"tags"`   //标签
    Press   string        `bson:"press"`  //出版社
}

//作者
type Author struct {
    Name string `bson:"name"` //姓名
    Sex  string `bson:"sex"`  //性别
}

const (
    BookCollection = "book"
)

func NewBook(name string, price float32, authors []Author, tags []string, press string) *Book {
    b := &Book{
        Name:    name,
        Price:   price,
        Authors: authors,
        Tags:    tags,
        Press:   press,
    }

    b.Id = bson.NewObjectId()

    return b
}

func insert() {
    //声明为interface数组,才能批量插入
    books := make([]interface{}, 0, 10)

    book1 := NewBook("高等数学上", 37.70, []Author{{"同济大学数学系", ""}}, []string{"数学", "大学数学", "高等数学"}, "高等教育出版社")
    books = append(books, book1)

    book2 := NewBook("TCP/IP详解卷1:协议", 45.00,
        []Author{{"W.Richard Stevens", ""}, {"范建华", ""}, {"胥光辉", ""}, {"张涛", ""}, {"谢希仁", ""}},
        []string{"计算机网络", "网络协议", "编程"}, "机械工业出版社")
    books = append(books, book2)

    book3 := NewBook("Python程序设计开发宝典", 69.00, []Author{{"董付国", ""}}, []string{"程序设计", "编程", "python"}, "清华大学出版社")
    books = append(books, book3)

    book4 := NewBook("汇编语言", 36.00, []Author{{"王爽", ""}}, []string{"程序设计", "编程", "汇编"}, "清华大学出版社")
    books = append(books, book4)

    book5 := NewBook("SparkSQL入门与实践指南", 49.00, []Author{{"纪涵", ""}, {"靖晓文", ""}, {"赵政达", ""}},
        []string{"程序设计", "编程", "spark", "spark sql"}, "清华大学出版社")
    books = append(books, book5)

    expr1 := func(c *mgo.Collection) error {
        return c.Insert(books...)
    }

    err := WithMongoCollection(BookCollection, expr1)
    if err != nil {
        fmt.Println(err.Error())
        return
    }

    fmt.Println("插入成功")
}

3.定义查询输出

func searchAll(query bson.M) {
    var books []Book
    expr := func(c *mgo.Collection) error {
        return c.Find(query).All(&books)
    }

    err := WithMongoCollection(BookCollection, expr)
    if err != nil {
        fmt.Println(err.Error())
        return
    }

    if len(books) == 0 {
        fmt.Println("未找到记录...")
        return
    }

    for _, book := range books {
        fmt.Println(book)
    }
}

4.简单条件查询

//单个条件 =
func equal() {
    query := bson.M{"name": "Python程序设计开发宝典"}
    searchAll(query)
}

//单个条件 >
func gt() {
    query := bson.M{"price": bson.M{"$gt": 40.0}}
    searchAll(query)
}

//单个条件 <
func lt() {
    query := bson.M{"price": bson.M{"$lt": 40.0}}
    searchAll(query)
}

//单个条件 >=
func gte() {
    query := bson.M{"price": bson.M{"$gte": 45}}
    searchAll(query)
}

//单个条件 <=
func lte() {
    query := bson.M{"price": bson.M{"$lte": 36}}
    searchAll(query)
}

//单个条件 !=
func ne() {
    query := bson.M{"press": bson.M{"$ne": "清华大学出版社"}}
    searchAll(query)
}

5. 多合条件查询

// and
//select * from table where price<=50 and press='清华大学出版社'
func and() {
    query := bson.M{"price": bson.M{"$lte": 50}, "press": "清华大学出版社"}
    searchAll(query)
}

// or
//select * from table where press='高等教育出版社' or press='清华大学出版社'
func or() {
    query := bson.M{"$or": []bson.M{bson.M{"press": "高等教育出版社"}, bson.M{"name": "Python程序设计开发宝典"}}}
    searchAll(query)
}

// not
// not条件只能用在正则表达式中
func not() {
    query := bson.M{"press": bson.M{"$not": bson.RegEx{Pattern: "^清华", Options: "i"}}}
    searchAll(query)
}


// 单个key的or查询可以使用 in 或 nin
func in() {
    query := bson.M{"press": bson.M{"$in": []string{"清华大学出版社", "机械工业出版社"}}}
    searchAll(query)
}

func nin() {
    query := bson.M{"press": bson.M{"$nin": []string{"清华大学出版社", "机械工业出版社"}}}
    searchAll(query)
}

6. 正则查询,字符串模糊查询

//正则查询
//$regex操作符的使用
//
//$regex操作符中的option选项可以改变正则匹配的默认行为,它包括i, m, x以及s四个选项,其含义如下
//
//i 忽略大小写,{<field>{$regex/pattern/i}},设置i选项后,模式中的字母会进行大小写不敏感匹配。
//m 多行匹配模式,{<field>{$regex/pattern/,$options:'m'},m选项会更改^和$元字符的默认行为,分别使用与行的开头和结尾匹配,而不是与输入字符串的开头和结尾匹配。
//x 忽略非转义的空白字符,{<field>:{$regex:/pattern/,$options:'m'},设置x选项后,正则表达式中的非转义的空白字符将被忽略,同时井号(#)被解释为注释的开头注,只能显式位于option选项中。
//s 单行匹配模式{<field>:{$regex:/pattern/,$options:'s'},设置s选项后,会改变模式中的点号(.)元字符的默认行为,它会匹配所有字符,包括换行符(\n),只能显式位于option选项中。
//
//使用$regex操作符时,需要注意下面几个问题:
//
//i,m,x,s可以组合使用,例如:{name:{$regex:/j*k/,$options:"si"}}
//在设置索引的字段上进行正则匹配可以提高查询速度,而且当正则表达式使用的是前缀表达式时,查询速度会进一步提高,例如:{name:{$regex: /^joe/}

//字符串模糊查询  开头包含
func beginWith() {
    query := bson.M{"name": bson.M{"$regex": bson.RegEx{Pattern: "^高等", Options: "i"}}}

    searchAll(query)
}

//模糊查询 包含
func contains() {
    //query := bson.M{"name": bson.M{"$regex": "开发", "$options": "$i"}}
    query := bson.M{"name": bson.M{"$regex": bson.RegEx{Pattern: "开发", Options: "i"}}}
    searchAll(query)
}

//模糊查询 结尾包含
func endWith() {
    query := bson.M{"name": bson.M{"$regex": bson.RegEx{Pattern: "指南$", Options: "i"}}}
    searchAll(query)
}

7.数组查询

//数组查询,数组中的元素可能是单个值数据,也可能是子文档
//针对单个值数据
//满足数组中单个值
func arrayMatchSingle() {
    query := bson.M{"tags": "编程"}
    searchAll(query)
}

//同时满足所有条件,不要求顺序
func arrayMatchAll() {
    query := bson.M{"tags": bson.M{"$all": []string{"程序设计", "编程", "python"}}}
    searchAll(query)
}

//查询特定长度
func arrayMatchSize() {
    query := bson.M{"tags": bson.M{"$size": 4}}
    searchAll(query)
}

//满足特定索引下条件
//数组索引从0开始,我们匹配第二项就用tags.1作为键
func arrayMatchIndex() {
    query := bson.M{"tags.1": "编程"}
    searchAll(query)
}

//精确查找,数量,顺序都要满足
func arrayMatch() {
    query := bson.M{"tags": []string{"数学", "大学数学", "高等数学"}}
    searchAll(query)
}

//针对与数组中的子文档
//满足单个价值
func subDocMatchSingle() {
    query := bson.M{"author.name": "纪涵"}
    searchAll(query)
}

//elementMath
func subDocMatchElement() {
    query := bson.M{"author": bson.M{"$elemMatch": bson.M{"name": "谢希仁", "sex": ""}}}
    searchAll(query)
}

8.聚合管道查询

 

//记数
func count() {
    var count int
    expr := func(c *mgo.Collection) error {
        var err error
        count, err = c.Find(bson.M{}).Count()
        return err
    }

    err := WithMongoCollection(BookCollection, expr)
    if err != nil {
        fmt.Println(err.Error())
        return
    }

    fmt.Println(count)
}


//去重
func distinct() {
    var result []interface{}
    expr := func(c *mgo.Collection) error {
        return c.Find(bson.M{}).Distinct("press", &result)
    }

    err := WithMongoCollection(BookCollection, expr)
    if err != nil {
        fmt.Println(err.Error())
        return
    }

    fmt.Println(result)

}


//求和
//golang mongo 管道查询中,可以先使用"$match"过滤出复合条件的数据,
//然后使用"$project"投射出想要的结果字段,然后使用 "$group" 进行分组聚合。
//"$group" 根据 "_id"来分组,可以通过多个字段来定义 "_id"来进行分组。

func sum() {
    query := []bson.M{
        //bson.M{"$match": bson.M{"press": "清华大学出版社"}},
        bson.M{"$project": bson.M{"_id": 0, "price": 1, "press": 1}},
        bson.M{"$group": bson.M{"_id": "$press", "totalPrice": bson.M{"$sum": "$price"}}},
    }

    var result []bson.M
    expr := func(c *mgo.Collection) error {
        return c.Pipe(query).All(&result)
    }

    err := WithMongoCollection(BookCollection, expr)
    if err != nil {
        fmt.Println(err.Error())
        return
    }

    fmt.Println(result)
}

//最大值和最小值
func maxAndMin() {
    query := []bson.M{
        bson.M{"$group": bson.M{"_id": nil,"maxPrice": bson.M{"$max": "$price"},"minPrice":bson.M{"$min":"$price"}}},
    }

    var result []bson.M
    expr := func(c *mgo.Collection) error {
        return c.Pipe(query).All(&result)
    }

    err := WithMongoCollection(BookCollection, expr)
    if err != nil {
        fmt.Println(err.Error())
        return
    }

    fmt.Println(result)
}

//平均值
func avg(){
    query := []bson.M{
        bson.M{"$group": bson.M{"_id": nil,"avgPrice": bson.M{"$avg": "$price"}}},
    }

    var result []bson.M
    expr := func(c *mgo.Collection) error {
        return c.Pipe(query).All(&result)
    }

    err := WithMongoCollection(BookCollection, expr)
    if err != nil {
        fmt.Println(err.Error())
        return
    }

    fmt.Println(result)
}

https://blog.csdn.net/tianwenxue/article/details/106316255

posted @ 2021-08-19 16:07  码农骆驼  阅读(2565)  评论(0编辑  收藏  举报