zoukankan      html  css  js  c++  java
  • 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选项后,会改变模式中的点号(.)元字符的默认行为,它会匹配所有字符,包括换行符(
    ),只能显式位于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

  • 相关阅读:
    c# winform DataGridView单击选中一整行,只能单选,不能选择多行,只能选择一行
    c# winform 子窗体向父窗体传值
    as中使用字体
    出现“正尝试安装的adobe flash player不是最新版本”的解决方法
    打印等腰三角形
    【Array数组】数组的浅复制和深复制
    AIR程序app.xml配置详解(转)
    【Array数组】使用slice返回数组中的元素
    creationComplete和applicationComplete区别
    【XML】遍历xml子节点
  • 原文地址:https://www.cnblogs.com/rxbook/p/15162318.html
Copyright © 2011-2022 走看看