查询
需求:输入为一个必选参数与任意多个可选参数,返回查询结果
新需求:
1. 关键字匹配(输入单个、部分或者整体字符,可查询出结果)
**思路:**模糊查询 + SQL拼接
object := g.Model("library").WhereLike("name", "%"+name+"%")
if PublisherId != 0 {
object = object.Where("publisher_id", PublisherId)
}
if ISBN != "" {
object = object.WhereOrLike("ISBN", "%"+ISBN+"%")
}
all, err := object.All()
2. 搜索字段在表数据中出现重复怎么办,即多条返回信息
如果想解决上述问题,需要返回多条信息
// 目前是这样的
{
"code": 0,
"message": "",
"data": {
"DeleteInformation": {
"id": 2,
"book_name": "*****",
"Book_ISBN": "*****",
"translator": "*****",
"publish_date": "2023-07-17 16:53:06",
"publisher_Id": 910
},
"message": "上述信息已删除"
}
}
// 想要的是这样的
{
"message": "",
"Data": [
{
"aa": "bb",
"cc": "dd"
},
{
"aa": "bb",
"cc": "dd"
}
]
}
怎么办?
分为三种情况解决:
-
查询结果为单数,直接返回
-
查询结果为多条信息,整体返回
-
查询结果为空
首先,设置对象类型的切片分层存储每一条数据,便于统计查询结果的数量。
Arr := make([]map[string]interface{}, 0)
for _, element := range all {
// 创建map数组存储每一个map,如arr1[ISBN]=78654132的元素
arr1 := make(map[string]interface{}, 0)
for key, value := range element {
arr1[gconv.String(key)] = value
}
Arr = append(Arr, arr1)
}
**其次,**如果查询结果为单数,直接返回:
if len(Arr) == 1 {
// 取出一个全局变量
globalVariable = gconv.Int(Arr[0]["id"])
BookSingle := v1.BookInformation{
....
Publisher_id: gconv.Int(Arr[0]["publisher_id"]),
}
arrResult = append(arrResult, BookSingle)
out = &v1.Q_Res{
Message: "图书信息如下",
Date: arrResult,
Flag: true,
}
}
**再次,**如果查询结果为多条数据,整体返回:
type UpdateRes struct {
Message string `json:"message"`
// 在返回值这做文章,把返回值作为数组
Date []BookInformation `json:"Updated_information"`
else { // 多条记录
for _, res := range Arr {
BookMulti := v1.BookInformation{
Id: gconv.Int(res["id"]),
...
Date: gconv.String(res["date"]),
Publisher_id: gconv.Int(res["publisher_id"]),
}
arrResult = append(arrResult, BookMulti)
}
out = &v1.Q_Res{
Message: "图书信息如下",
Date: arrResult,
Flag: true,
}
}
**最后,**查询结果为空:
if len(Arr) == 0 {
g.RequestFromCtx(ctx).Response.ResponseWriter.WriteHeader(500)
out = &v1.Q_Res{
Message: "查询结果为空",
Date: []v1.BookInformation{},
Flag: false,
}
return
}
3. 搜索字段在表中出现重复数据,用户通过添加约束条件,逐步锁定查询目标
利用SQL中"and"与"or"的优先级来解决
// all, err := g.Model("library").Ctx(ctx).Where("name", name).WhereOr("ISBN", ISBN).Where("publisher_id", PublisherId).All()
// 是0就不执行AND (`publisher_id`=PublisherId),
// 只执行WHERE (`name`='name') OR (`ISBN`='')
// 不是0的话,就把这句加上,并且在Where("name", "许三观卖血记")与Where("publisher_id", pub)之间构造and
object := g.Model("library").Where("name", name)
if PublisherId != 0 {
object = object.Where("publisher_id", PublisherId)
}
object = object.WhereOr("ISBN", ISBN)
all, err := object.All()
增加
需要完整的图书信息,也要事先判断是否已经存在该记录(先查询),如果已经存在,则不能重复添加
首先,判断表中是否已经存在该数据
flag, err := g.Model("library").Ctx(ctx).Fields("count(1)", "id").Where("name", in.Date.Name).Where("ISBN", in.Date.ISBN).Where(
"translator", in.Date.Translator).Where("date", in.Date.Date).WhereOr("publisher_id", in.Date.Publisher_id).Group("id").All()
if err != nil {
return out, err
}
存在,则直接返回
// 要插入的数据已经存在于表中
if flag != nil {
out = &v1.InsertRes{
Message: "数据已存在,不可添加",
Date: v1.BookInformation{},
}
return
}
否则,插入
增加操作(插入、新建)比较简单了,但是需要提前判断**当前添加信息的所有字段,在原有库中是否有完全匹配的
**,如果有则无法插入,否则正常插入即可。
修改
总体:先查询出要修改的信息,然后再修改
— 1. 根据书名
或者ISBN
进行查询(输入)
---- 1.1 查询结果存在
----- 1.1.1 查询结果为单条:设置全局变量保存主键值,返回该图书完整的信息和message提示
----- 1.1.2 查询结果为多条:返回各个图书完整的信息和message提示
---- 1.2 查询结果不存在
----- 1.2.1 返回查询失败的message提示
— 2. 对查询到的信息进行“有选择地”修改
// 开启事务
// 当给定的闭包方法返回的error为nil时,闭包执行结束后当前事务自动执行Commit提交操作;否则自动执行Rollback回滚操作。
dao.GfUser.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
// 为了防止空字段覆盖原始字段,提前设置一个map对象备份(倒腾)
data := gmap.New()
// 不为"",即证明有值,也就是需要修改,其余的不用修改,晕了
if gconv.String(in.Information.Name) != "" {
data.Set("name", in.Information.Name)
}
if gconv.String(in.Information.ISBN) != "" {
data.Set("ISBN", in.Information.ISBN)
}
if gconv.String(in.Information.Translator) != "" {
data.Set("translator", in.Information.Translator)
}
if gconv.String(in.Information.Date) != "" {
data.Set("date", in.Information.Date)
}
if gconv.Int(in.Information.Publisher_id) != 0 {
data.Set("publisher_id", in.Information.Publisher_id)
}
_, err = g.Model("library").Data(data.Map()).Where("id", val).Update()
if err != nil {
return err
} else {
return nil
}
})
---- 2.1 修改成功
----- 2.1.1 针对单条查询结果,可直接修改
----- 2.1.2 针对多条查询结果,需指定要修改图书的ID信息
// update library set name = '背影',ISBN = '132456789',translator = 'qiqi', date = now(),publisher_id = '110' where id = 4;
all2, err2 := g.Model("library").Ctx(ctx).Where("id", val).All()
if err2 != nil {
err = err2
return
}
outUpdated = &v1.UpdateRes{
Message: "修改后的信息如下",
Date: v1.BookInformation{
Id: gconv.Int(all2[0]["id"]),
Name: gconv.String(all2[0]["name"]),
ISBN: gconv.String(all2[0]["ISBN"]),
Translator: gconv.String(all2[0]["translator"]),
Date: gconv.String(all2[0]["date"]),
Publisher_id: gconv.Int(all2[0]["publisher_id"]),
},
}
return
返回修改后的该图书完整信息和message提示
---- 2.2 修改失败
----- 2.2.1 返回修改的message提示
Map类型的输出不明白?一次搞懂:
count, err := g.Model("library").Fields("count(1),id").Where("name", s1).WhereOr("ISBN", s2).Group("id").All()
if err != nil {
return
}
// 直接输出
fmt.Println(count)
// 输出
// [map[count(1):1 id:1]] 分析:输出的是一个数组[],里面包了一个map,map有两个key-value,第一个key是count(1),value是1;第二个key是id,value是1。
fmt.Println(count[0]) //取数组第一个元素
// 输出
// map[count(1):1 id:1]
fmt.Println(count[0]["count(1)"]) // 取数组第一个元素的map里的第一个key所对应的值
// 输出
// 1
fmt.Println(count[0]["id"]) // 取数组第一个元素的map里的第二个key所对应的值
// 输出
// 1
删除
—需求:
// 只需要提供其中一个name或者ISBN(唯一)即可查询到数据并进行删除
— 1. 根据书名
或者ISBN
进行查询(输入)
---- 1.1 查询结果存在
----- 1.1.1 查询结果为单条信息
返回该图书完整的信息,直接删除
flag, err := s.Query(ctx, in.Name, in.ISBN, in.PublisherID)
if flag.Flag {
ArrResult2 := make([]v1.BookInformation, 0)
// 如果为一条图书信息
if len(flag.Date) == 1 {
_, err2 := g.Model("library").Where("publisher_id", flag.Date[0].Publisher_id).Delete()
if err2 != nil {
return
}
bookSingle := v1.BookInformation{
Id: flag.Date[0].Id,
Name: flag.Date[0].Name,
ISBN: flag.Date[0].ISBN,
Translator: flag.Date[0].Translator,
Date: flag.Date[0].Date,
Publisher_id: flag.Date[0].Publisher_id,
}
ArrResult2 = append(ArrResult2, bookSingle)
OutDeleted = &v1.DeleteRes{
Message: "删除信息如下",
Date: ArrResult2,
}
}
----- 1.1.2 查询结果为多条信息
------ 1.1.2.1 指定了PublisherID(问题是,你指定了PublisherID,查询结果就不可能是多条了)所以这一条省略。
根据PublisherID返回该图书完整的信息,并对图书信息进行删除操作,最后返回Message提示:图书信息已删除
// 如果图书信息为多条
if len(flag.Date) > 1 {
// flag.Date已经是一个数组了,那就直接返回可以吗
OutDeleted = &v1.DeleteRes{
Message: "请指定图书publisher_id,再次进行删除",
Date: flag.Date,
}
}
执行删除操作,成功后返回message提示:“已删除”
---- 1.2 查询结果不存在
----- 1.2.1 返回删除失败的message提示:图书信息不存在,无法删除
// 如果图书信息不存在
if !flag.Flag {
OutDeleted = &v1.DeleteRes{
Date: []v1.BookInformation{},
Message: "图书信息不存在",
}
return
}
直接返回可以吗
OutDeleted = &v1.DeleteRes{
Message: “请指定图书publisher_id,再次进行删除”,
Date: flag.Date,
}
}
#### **执行删除操作,成功后返回message提示:“已删除”**
#### ---- 1.2 查询结果不存在
##### ----- 1.2.1 返回删除失败的message提示:图书信息不存在,无法删除
```go
// 如果图书信息不存在
if !flag.Flag {
OutDeleted = &v1.DeleteRes{
Date: []v1.BookInformation{},
Message: "图书信息不存在",
}
return
}