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.聚合管道查询
定义[]bson.M查询条件数组,依次执行
//记数
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)
}