Not in condition using gorm in golang – dynamic not in condition for select statement

huangapple go评论148阅读模式
英文:

Not in condition using gorm in golang - dynamic not in condition for select statement

问题

我有两个数据库,Booking和Room。Booking数据库中有一个字段roomid。我编写了一个select语句,将检索到的行保存在result变量中,如下所示:

var result models.Booking
rows, err := utils.DB.Model(&currRequest).Where("check_in BETWEEN ? AND ? AND check_out BETWEEN ? AND ?", currRequest.CheckIn, currRequest.CheckOut, currRequest.CheckIn, currRequest.CheckOut).Select("room_id").Rows()
for rows.Next() {
    utils.DB.ScanRows(rows, &result)
    fmt.Println(result.RoomID)
}

现在,我的result.roomid中有满足bookings表中select语句的roomid值。

我的result变量可能有多个room id值。我可以通过循环遍历result变量来检索roomid值。现在,我需要在名为Room的主要房间数据库中检查那些不在result结构中的room id。使用下面的语句,我只能访问result.roomid中的第一个值,因此notin条件只考虑result.roomid中的第一个值。如何对result.roomid中的所有值执行notin条件?

rows, err := utils.DB.Model(&models.Room{}).Not(result.RoomID).Select("room_id").Rows()

完整代码:

package handlers

import (
    "encoding/json"
    "fmt"
    "net/http"
    "server/models"
    "server/utils"
    "strings"
)

func AvailableRoomsHandler(w http.ResponseWriter, r *http.Request) {

    currRequest := &models.Booking{}
    err := json.NewDecoder(r.Body).Decode(currRequest)
    // 检查是否从前端发送了有效请求
    if err != nil {
        var resp = map[string]interface{}{"status": false, "message": "无效的JSON请求"}
        json.NewEncoder(w).Encode(resp)
        return
    }

    noOfRoomsOccupied := 0
    var notinrooms string

    // 使用GORM API构建SQL
    // 检查在请求的入住和退房日期中是否有任何尚未预订的可用房间
    var result models.Booking
    rows, err := utils.DB.Model(&currRequest).Where("check_in BETWEEN ? AND ? AND check_out BETWEEN ? AND ?", currRequest.CheckIn, currRequest.CheckOut, currRequest.CheckIn, currRequest.CheckOut).Select("room_id").Rows()
    if err != nil {
        json.NewEncoder(w).Encode(err)
        fmt.Print("在select语句中发生错误")
        return
    } else {
        defer rows.Close()
        for rows.Next() {
            noOfRoomsOccupied = noOfRoomsOccupied + 1
            utils.DB.ScanRows(rows, &result)
            fmt.Println(result.RoomID)
            notinrooms = notinrooms + result.RoomID + ","
        }
        notinrooms = strings.TrimRight(notinrooms, ",")
        fmt.Println(notinrooms)
        // 计算数据库中的房间数量
        res := utils.DB.Find(&models.Room{})
        rowcount := res.RowsAffected
        fmt.Println(rowcount)
        if noOfRoomsOccupied == int(rowcount) {
            var resp = map[string]interface{}{"status": false, "message": "在指定的时间段内没有可用房间"}
            json.NewEncoder(w).Encode(resp)
            return
        } else {
            noOfRooms := (currRequest.NoOfGuests + currRequest.NoOfChildren) / 2
            if (currRequest.NoOfGuests+currRequest.NoOfChildren)%2 == 1 {
                noOfRooms = noOfRooms + 1
            }
            if int(noOfRooms) < int(rowcount)-noOfRoomsOccupied {
                fmt.Println("要预订的房间数量:", noOfRooms)
                // 如果有可用的房间,则分配房间
                var roomids models.Room
                fmt.Println("可以预订的房间")
                rows, err := utils.DB.Model(&models.Room{}).Not(result.RoomID).Select("room_id").Rows()
                if err != nil {
                    json.NewEncoder(w).Encode(err)
                    fmt.Print("在选择语句中获取要分配的房间ID时发生错误")
                    return
                } else {
                    defer rows.Close()
                    for rows.Next() {
                        noOfRoomsOccupied = noOfRoomsOccupied + 1
                        utils.DB.ScanRows(rows, &roomids)
                        fmt.Println(roomids.RoomID)
                    }
                }
                var success = map[string]interface{}{"message": "选择语句运行良好"}
                json.NewEncoder(w).Encode(success)
                return
            }
        }
    }
}

当我使用result.roomid时,它只给出第一个房间id,并且只在上述select语句中排除该房间id。如何在rooms表数据中排除我在booking表中找到的所有room id?

我尝试拆分result.roomid值并尝试形成一个字符串,并将其放入select语句中,但这没有起作用。我尝试循环遍历每个result.roomid并运行notin语句,但这没有任何意义。

英文:

I have two databases Booking and Room. Booking has roomid as one of its field. I wrote a select statement which saves the rows retrieved in result variable as stated below.

var result models.Booking
rows, err := utils.DB.Model(&amp;currRequest).Where(&quot;check_in BETWEEN ? AND ? AND check_out BETWEEN ? AND ?&quot;, currRequest.CheckIn, currRequest.CheckOut, currRequest.CheckIn, currRequest.CheckOut).Select(&quot;room_id&quot;).Rows()
for rows.Next() {
utils.DB.ScanRows(rows, &amp;result)
fmt.Println(result.RoomID)
}

Now my result.roomid has values of roomids that satisfy the select statement from the bookings table

My result variable may have multiple room id values. I am able to retrieve the roomid values by looping through the result variable. Now I have to check in my main room database called Room and get those room ids that are not in the result struct. By using the below statement, I am only able to access the first value in result.roomid so the not in condition only considers the first values in result.roomid. How do I do the not in condition for all the values in result.roomid?

rows, err := utils.DB.Model(&amp;models.Room{}).Not(result.RoomID).Select(&quot;room_id&quot;).Rows()

Full code:

package handlers
import (
&quot;encoding/json&quot;
&quot;fmt&quot;
&quot;net/http&quot;
&quot;server/models&quot;
&quot;server/utils&quot;
&quot;strings&quot;
)
func AvailableRoomsHandler(w http.ResponseWriter, r *http.Request) {
currRequest := &amp;models.Booking{}
err := json.NewDecoder(r.Body).Decode(currRequest)
//check if a valid request has been sent from front end
if err != nil {
//fmt.Println(err)
var resp = map[string]interface{}{&quot;status&quot;: false, &quot;message&quot;: &quot;Invalid json request&quot;}
json.NewEncoder(w).Encode(resp)
return
}
noOfRoomsOccupied := 0
var notinrooms string
// Use GORM API build SQL
//check if any rooms are available which havent been booked yet in the requested check-in and check-out dates
var result models.Booking
rows, err := utils.DB.Model(&amp;currRequest).Where(&quot;check_in BETWEEN ? AND ? AND check_out BETWEEN ? AND ?&quot;, currRequest.CheckIn, currRequest.CheckOut, currRequest.CheckIn, currRequest.CheckOut).Select(&quot;room_id&quot;).Rows()
if err != nil {
json.NewEncoder(w).Encode(err)
fmt.Print(&quot;error occured in select statement&quot;)
return
} else {
defer rows.Close()
for rows.Next() {
noOfRoomsOccupied = noOfRoomsOccupied + 1
utils.DB.ScanRows(rows, &amp;result)
fmt.Println(result.RoomID)
notinrooms = notinrooms + result.RoomID + &quot;,&quot;
}
notinrooms = strings.TrimRight(notinrooms, &quot;,&quot;)
fmt.Println(notinrooms)
//calculate the number of rooms in the database
//rows, err := utils.DB.Model(&amp;models.Room{}).Select(&quot;room_id&quot;).Rows()
res := utils.DB.Find(&amp;models.Room{})
rowcount := res.RowsAffected
fmt.Println(rowcount)
if noOfRoomsOccupied == int(rowcount) {
var resp = map[string]interface{}{&quot;status&quot;: false, &quot;message&quot;: &quot;no rooms available in the specified time period&quot;}
json.NewEncoder(w).Encode(resp)
return
} else {
noOfRooms := (currRequest.NoOfGuests + currRequest.NoOfChildren) / 2
if (currRequest.NoOfGuests+currRequest.NoOfChildren)%2 == 1 {
noOfRooms = noOfRooms + 1
}
if int(noOfRooms) &lt; int(rowcount)-noOfRoomsOccupied {
fmt.Println(&quot;number of rooms to book : &quot;, noOfRooms)
//assign rooms if available
var roomids models.Room
//rows, err := utils.DB.Model(&amp;models.Room{}).Not(result.RoomID).Select(&quot;room_id&quot;).Rows()
fmt.Println(&quot;rooms that can be booked&quot;)
rows, err := utils.DB.Model(&amp;models.Room{}).Not(result.RoomID).Select(&quot;room_id&quot;).Rows()
//rows, err := utils.DB.Model(&amp;models.Room{}).Not([]string{notinrooms}).Select(&quot;room_id&quot;).Rows()
//map[string]interface{}{&quot;name&quot;: []string{&quot;jinzhu&quot;, &quot;jinzhu 2&quot;}}
if err != nil {
json.NewEncoder(w).Encode(err)
fmt.Print(&quot;error occured in select statement to get room ids to assign&quot;)
return
} else {
defer rows.Close()
for rows.Next() {
noOfRoomsOccupied = noOfRoomsOccupied + 1
utils.DB.ScanRows(rows, &amp;roomids)
fmt.Println(roomids.RoomID)
}
}
var success = map[string]interface{}{&quot;message&quot;: &quot;Select statement worked well&quot;}
json.NewEncoder(w).Encode(success)
return
}
}
}
}

When I do result.roomid, it only gives the first room id and eliminates only that room id in the above select statement. How do I eliminate all the room ids I found in the booking table in the rooms table data?

I tried splitting the result.roomid values and tried to form a string and gave it in the select statement but that didn't work. I tried looping through every result.roomid and ran the not in a statement but that will not make any sense.

答案1

得分: 0

使用以下代码:

var result []models.Booking
rows, err := utils.DB.Model(&currRequest).Where("check_in BETWEEN ? AND ? AND check_out BETWEEN ? AND ?", currRequest.CheckIn, currRequest.CheckOut, currRequest.CheckIn, currRequest.CheckOut).Select("room_id").Rows()
if err != nil {
    json.NewEncoder(w).Encode(err)
    fmt.Print("在选择语句中发生错误")
    return
} else {
    defer rows.Close()
    for rows.Next() {
        var b models.Booking
        noOfRoomsOccupied = noOfRoomsOccupied + 1
        utils.DB.ScanRows(rows, &b)
        result = append(result, b)
        // 其余代码
    }
}

然而,由于你只需要roomid,你可以通过使用[]uint(假设roomid的类型为uint)来简化操作。

var result []uint
rows, err := utils.DB.Model(&currRequest).Where("check_in BETWEEN ? AND ? AND check_out BETWEEN ? AND ?", currRequest.CheckIn, currRequest.CheckOut, currRequest.CheckIn, currRequest.CheckOut).Select("room_id").Rows()
if err != nil {
    json.NewEncoder(w).Encode(err)
    fmt.Print("在选择语句中发生错误")
    return
} else {
    defer rows.Close()
    for rows.Next() {
        var rid uint
        noOfRoomsOccupied = noOfRoomsOccupied + 1
        utils.DB.ScanRows(rows, &rid)
        result = append(result, rid)
        // 其余代码
    }
}

使用类型为[]uintresult,可以更容易地将其与Not函数一起使用(参考文档):

rows, err := utils.DB.Model(&models.Room{}).Not(result).Select("room_id").Rows()
英文:

With this code:

var result models.Booking
rows, err := utils.DB.Model(&amp;currRequest).Where(&quot;check_in BETWEEN ? AND ? AND check_out BETWEEN ? AND ?&quot;, currRequest.CheckIn, currRequest.CheckOut, currRequest.CheckIn, currRequest.CheckOut).Select(&quot;room_id&quot;).Rows()
if err != nil {
json.NewEncoder(w).Encode(err)
fmt.Print(&quot;error occured in select statement&quot;)
return
} else {
defer rows.Close()
for rows.Next() {
noOfRoomsOccupied = noOfRoomsOccupied + 1
utils.DB.ScanRows(rows, &amp;result)
//rest of the code
}
}

you only get one row of potentially many rows from the result set. To get all the rows and extract their values, you should use []models.Booking.

result := []models.Booking{}
rows, err := utils.DB.Model(&amp;currRequest).Where(&quot;check_in BETWEEN ? AND ? AND check_out BETWEEN ? AND ?&quot;, currRequest.CheckIn, currRequest.CheckOut, currRequest.CheckIn, currRequest.CheckOut).Select(&quot;room_id&quot;).Rows()
if err != nil {
json.NewEncoder(w).Encode(err)
fmt.Print(&quot;error occured in select statement&quot;)
return
} else {
defer rows.Close()
for rows.Next() {
var b models.Booking
noOfRoomsOccupied = noOfRoomsOccupied + 1
utils.DB.ScanRows(rows, &amp;b)
result = append(result, b)
//rest of the code
}
}

However, since you only need roomid anyway, you could make it easier by using []uint (assuming roomid is of type uint).

result := []uint{}
rows, err := utils.DB.Model(&amp;currRequest).Where(&quot;check_in BETWEEN ? AND ? AND check_out BETWEEN ? AND ?&quot;, currRequest.CheckIn, currRequest.CheckOut, currRequest.CheckIn, currRequest.CheckOut).Select(&quot;room_id&quot;).Rows()
if err != nil {
json.NewEncoder(w).Encode(err)
fmt.Print(&quot;error occured in select statement&quot;)
return
} else {
defer rows.Close()
for rows.Next() {
var rid uint
noOfRoomsOccupied = noOfRoomsOccupied + 1
utils.DB.ScanRows(rows, &amp;rid)
result = append(result, rid)
//rest of the code
}
}

With the result being of type []uint, it would be easier to use it with the Not function (per documentation):

rows, err := utils.DB.Model(&amp;models.Room{}).Not(result).Select(&quot;room_id&quot;).Rows()

huangapple
  • 本文由 发表于 2022年3月25日 00:44:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/71606292.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定