一对多查询语句_如何连接mongodb数据库

(30) 2024-08-22 11:01:08

   Hello,各位小伙伴,大家好呀。老哥周六要加班,好累…,真的不想加班,但是没有办法,为了Money,只能忍一下。

   老哥趁着下午摸鱼的时间,我们来学习一下Gorm

1、首先导入gorm包,参考文档,https://learnku.com/docs/gorm/v2/index/9728

PS D:\Project\Go_Project\goproject1> go get -u gorm.io/gorm PS D:\Project\Go_Project\goproject1> go get -u gorm.io/driver/sqlite 

2、然后我们需要使用mysql,导入mysql的驱动包

D:\Project\Go_Project\goproject1> go get -u github.com/go-sql-driver/mysql 

3、 gorm连接到Mysql数据库,使用Api,创建students表结构

补充: 里面有个创建表结构的方法,但是没有数据,老哥这里提供一下数据(当然你也可以自己造 dog狗头保命)

INSERT INTO students VALUES (1, ‘Jessica’, 25);
INSERT INTO students VALUES (2, ‘Jerry’, 26);
INSERT INTO students VALUES (3, ‘Tom’, 18);
INSERT INTO students VALUES (4, ‘lili’, 18);

package main import ( "fmt" "gorm.io/driver/mysql" "gorm.io/gorm" "log" ) type Student struct { 
    Id int Name string Age int } func initGormDb() *gorm.DB { 
    dsn := "root:root@tcp(127.0.0.1:3306)/go-test?charset=utf8mb4&parseTime=True&loc=Local" dbs, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ 
    //如果不想看到日志sql,这里可以关掉 Logger: logger.Default.LogMode(logger.Info), }) if err != nil { 
    panic("gorm failed to connect Mysql...") } return dbs } // CreateTable 创建表 func CreateTable(db *gorm.DB) { 
    err := db.AutoMigrate(&Student{ 
   }) if err != nil { 
    log.Println("failed to create table...") return } } func main() { 
    db := initGormDb() //1、创建表 CreateTable(db) } 

3A、插入数据,支持批量插入(CreateInBatches ),具体参考,https://learnku.com/docs/gorm/v2/create/9732

//InsertData func InsertData(db *gorm.DB) { 
    //插入一条 //p := Student{ 
    // Name: "uzi", // Age: 25, //} //tx := db.Create(&p) //fmt.Println(tx.RowsAffected) //插入多条 p2 := Student{ 
    Name: "gala", Age: 20, } p3 := Student{ 
    Name: "wei", Age: 19, } txs := db.Create(&[]Student{ 
   p2, p3}) fmt.Println(txs.RowsAffected) } 

5、查询数据,因为查询的话,没有固定的写法,老哥这里只是列举了常用的,详情参考,https://learnku.com/docs/gorm/v2/advanced_query/9757

// SelectData 查询数据 /** 查询五花八门,我们可以按照需要进行定制查询 */ func SelectData(db *gorm.DB) { 
    //1、保存多条数据 var stuList []Student //2、保存单条数据 var stu Student //按照主键查找 //db.First(&stu, 2) //带条件查询,查一条 //db.First(&stu, "age=?", 18) // 获取最后一条记录(主键降序) //db.Last(&stu) //获取全部数据 //db.Find(&stuList) //where查询单条数据 //db.Where("age=?", 25).Find(&stu) //db.Where(&Student{Age: 18}).Find(&stu) //fmt.Println(stu) //where查询多条数据 //db.Where("age=?", 18).Find(&stuList) //where查询多条数据 or //db.Where("age=? or age=?", 25, 26).Find(&stuList) //db.Where("age=?", 18).Or("age=?", 26).Find(&stuList) //fmt.Println(stuList) //where查询通过单条数据 Map db.Where(map[string]interface{ 
   }{ 
   "name": "uzi", "age": 25}).Find(&stu) fmt.Println(stu) //BETWEEN 查询年龄25到30 //db.Where("age BETWEEN ? AND ?", 25, 30).Find(&stuList) //fmt.Println(stuList) //order查询 按照年龄降序,默认是升序 //db.Order("age desc").Find(&stuList) //fmt.Println(stuList) //limit查询,查询前3条数据 //db.Limit(3).Find(&stuList) //fmt.Println(stuList) //Offset 跳过几条,查询前3条数据 //db.Limit(3).Offset(1).Find(&stuList) //fmt.Println(stuList) //Distinct 按照年龄去重,返回不重复的年龄 //db.Distinct("age").Find(&stuList) //fmt.Println(stuList) //Group分组 等同于 select age from students group by age //db.Select("age").Group("age").Find(&stuList) //fmt.Println(stuList) //Having 查询年龄大于20 db.Having("age > ?", 20).Find(&stuList) fmt.Println(stuList) } 

6、更新数据,参考资料,https://learnku.com/docs/gorm/v2/update/9734

// UpdateStudentData 更新数据 func UpdateStudentData(db *gorm.DB) { 
    //单条更新 修改Jessica的年龄为18 //update := db.Model(Student{}).Where("name=?", "Jessica").Update("age", 18) //fmt.Println(update.RowsAffected) //批量更新 修改id为 6、7,年龄统一改为19 updates := db.Table("students").Where("id In ?", []int{ 
   6, 7}).Updates(map[string]interface{ 
   }{ 
   "age": 19}) fmt.Println(updates.RowsAffected) } 

7、删除数据,注意这里增加了一个钩子,在删除之前,我们可以加一些属于自己的逻辑

//DeleteData 删除数据 func DeleteData(db *gorm.DB) { 
    //单条删除 删除id为7的数据 //deleteCount := db.Delete(&Student{}, "7") //fmt.Println(deleteCount.RowsAffected) //批量删除 删除id为5、6的数据 //deleteCountList := db.Delete(&Student{}, []int{5, 6}) //fmt.Println(deleteCountList.RowsAffected) //删除钩子,因为删除一般是危险动作,我们可以考虑删除加个判断 //BeforeDelete 会在删除之前,自动调用 //下面的方法均不会触发钩子 //1. //db.Delete(&User{}, 1) 2. //db.Delete(&User{}, "id in ?", ids) 3. //var ids = []uint{1,2,3} //db.Where("id in ?",ids).Delete(&User{}) //钩子触发条件,stu里面必须有数据  //下面这种会触发钩子,单条删除 //var stu Student //db.Where("id =3").Find(&stu).Delete(&stu) //下面这种会触发钩子,多条删除 //var stuList []Student //var ids = []uint{1, 2, 3} //db.Where("id in ?", ids).Find(&stuList).Delete(&stuList) //删除全部数据,不会触发钩子 db.Where("id > ?", 0).Delete(&Student{ 
   }) } func (stu *Student) BeforeDelete(tx *gorm.DB) (err error) { 
    if stu.Name == "Jerry" { 
    fmt.Println("Jerry not allowed to delete") return errors.New("Jerry not allowed to delete") } return } 

8、gorm基本的增删改查先介绍到这里,已经可以满足开发的日常需要。下面介绍一下,Gorm进阶
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------->

9、gorm 支持我们写原生Sql,最大限度让我们自由发挥

//RawSql 支持原生sql func RawSql(db *gorm.DB) { 
    var stuList []Student // SELECT * FROM students WHERE name = "Jessica" OR name2 = "Tom" db.Raw("SELECT * FROM students WHERE name = @name1 OR name = @name2", sql.Named("name1", "Jessica"), sql.Named("name2", "Tom")).Find(&stuList) fmt.Println(stuList) // UPDATE students SET age = 20 where id in (2,3)" //db.Exec("UPDATE students SET age = @ages where id in (2,3)", // sql.Named("ages", 20)) } 

10、一对多, 我们先创建表结构,然后插入数据

type Company struct { 
    ID uint `gorms:"primarykey"` Name string Workers []Worker //用来存放查询出来的所有打工人 } type Worker struct { 
    ID uint `gorms:"primarykey"` WorkerName string CompanyID uint } func main() { 
    db := initGormDb() //创建表,先有公司,然后有打工人 //db.AutoMigrate(&Company{}, &Worker{}) } 

INSERT INTO companies VALUES (1, ‘jdg’);

INSERT INTO workers VALUES (‘yagao’, 1);
INSERT INTO workers VALUES (‘369’, 1);
INSERT INTO workers VALUES (‘kanavi’, 1);
INSERT INTO workers VALUES (‘hope’, 1);
INSERT INTO workers VALUES (‘missing’, 1);

package main import ( "bytes" "encoding/json" "fmt" "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" ) func initGormDb() *gorm.DB { 
    dsn := "root:root@tcp(127.0.0.1:3306)/go-test?charset=utf8mb4&parseTime=True&loc=Local" dbs, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ 
    //如果不想看到日志sql,这里可以关掉 Logger: logger.Default.LogMode(logger.Info), }) if err != nil { 
    panic("gorms failed to connect Mysql...") } return dbs } type Company struct { 
    ID uint `gorms:"primarykey"` Name string Workers []Worker //用来存放查询出来的所有打工人 } type Worker struct { 
    ID uint `gorms:"primarykey"` WorkerName string CompanyID uint } func PrintJsonTree(obj interface{ 
   }) { 
    marshal, err := json.Marshal(obj) //这里是把JSON格式,树形化输出,优雅地展示 var treeJSON bytes.Buffer err = json.Indent(&treeJSON, marshal, "", "\t") fmt.Println(string(treeJSON.Bytes())) if err != nil { 
    panic(err) } } func main() { 
    db := initGormDb() //创建表,先有公司,然后有打工人 //db.AutoMigrate(&Company{}, &Worker{}) //1、一对多,一个公司有多名员工,插入数据 //w1 := Worker{ 
    // ID: 8, // WorkerName: "knight", //} // //w2 := Worker{ 
    // ID: 9, // WorkerName: "tian", //} // //c := Company{ 
    // ID: 3, // Name: "tes", // Workers: []Worker{w1, w2}, //} // //db.Create(&c) //2、一对多,一个公司有多名员工,查询数据 //查询公司为jdg的信息 var company Company //注意:Workers取得是 Workers []Worker 的变量,Preload预加载 //它会先 SELECT * FROM `workers` WHERE `workers`.`company_id` = 1 //然后 SELECT * FROM `companies` WHERE `companies`.`id` = '1' db.Preload("Workers").Find(&company, "1") //Preload 还可以增加你想要的条件,比如,我只带369出来 //Worker_Name 对应数据库的 Worker_Name //db.Preload("Workers", "Worker_Name=?", "369").Find(&company, "1") PrintJsonTree(company) } 

一对多,打印结果如下:

一对多查询语句_如何连接mongodb数据库 (https://mushiming.com/)  第1张

11、多对一

 //多对一查询 //多个打工人,对应一个公司,查询数据 var WorkList []Worker //查询所有在jdg的员工信息,多对一 db.Where("company_id =? ", 1).Find(&WorkList) PrintJsonTree(WorkList) 

多对一,查询结果如下:

一对多查询语句_如何连接mongodb数据库 (https://mushiming.com/)  第2张

12、多对多,注意:多对多插入数据要分两次插入,因为中间表的插入,第二次不能再新增ID

package main import ( "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" ) func initGormDb() *gorm.DB { 
    dsn := "root:root@tcp(127.0.0.1:3306)/go-test?charset=utf8mb4&parseTime=True&loc=Local" dbs, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ 
    //如果不想看到日志sql,这里可以关掉 Logger: logger.Default.LogMode(logger.Info), }) if err != nil { 
    panic("gorms failed to connect Mysql...") } return dbs } // User 拥有并属于多种 language,`user_languages` 是连接表 type User struct { 
    gorm.Model UserName string Languages []Language `gorm:"many2many:user_languages;"` //加了这个,需要绑定另外一个many2many,然后会创建一张中间表 } type Language struct { 
    gorm.Model Name string Users []User `gorm:"many2many:user_languages;"` //加了这个,需要绑定另外一个many2many,然后会创建一张中间表 } //多对多 func main() { 
    db := initGormDb() db.AutoMigrate(&User{ 
   }, &Language{ 
   }) //第一次插入需要 u1 := User{ 
    UserName: "大佬1号", } u2 := User{ 
    UserName: "大佬2号", } l1 := Language{ 
    Name: "English", Users: []User{ 
   u1, u2}, } // 第一次插入数据,英语有两个大佬学 db.Create(&l1) } 

第二次插入数据,u1 u2 l2三处调整

//多对多 func main() { 
    db := initGormDb() //db.AutoMigrate(&User{}, &Language{}) u1 := User{ 
    Model:gorm.Model{ 
    ID: 1, }, UserName: "大佬1号", } u2 := User{ 
    Model:gorm.Model{ 
    ID: 2, }, UserName: "大佬2号", } //l1 := Language{ 
    // Name: "English", // Users: []User{u1, u2}, //} l2 := Language{ 
    Name: "Math", Users: []User{ 
   u1, u2}, } // 第一次插入数据,英语有两个大佬学 //db.Create(&l1) //第二次插入,数学有两个大佬学 db.Create(&l2) } 

如果是正常插入,中间表 user_languages 的显示如下:

一对多查询语句_如何连接mongodb数据库 (https://mushiming.com/)  第3张

13、然后多对多,打印输出

func PrintJsonTrees(obj interface{ 
   }) { 
    marshal, err := json.Marshal(obj) //这里是把JSON格式,树形化输出,优雅地展示 var treeJSON bytes.Buffer err = json.Indent(&treeJSON, marshal, "", "\t") fmt.Println(string(treeJSON.Bytes())) if err != nil { 
    panic(err) } } //多对多 func main() { 
    db := initGormDb() //多对多查询 var UserList []User db.Preload("Languages").Find(&UserList) PrintJsonTrees(UserList) } 

多对多,结果查询如下:

一对多查询语句_如何连接mongodb数据库 (https://mushiming.com/)  第4张

14、最后,各位小伙伴,麻烦给老哥一个点赞、关注、收藏三连好吗,你的支持是老哥更新最大的动力,谢谢!

THE END

发表回复