select plus - xs-soft/dbr GitHub Wiki
高级查询操作
支持使用map结构取得多行记录 以字段名作为每行map的键
datas:=[]map[string]string{}
dbr.Select("*").From("user").Load(&datas)
来自于dbr的测试用例
直接上原版测试用例代码 Load操作之Map
func TestMaps(t *testing.T) {
for _, sess := range testSession {
reset(t, sess)
_, err := sess.InsertInto("dbr_people").
Columns("name", "email").
Values("test1", "[email protected]").
Values("test2", "[email protected]").
Values("test2", "[email protected]").
Exec()
//如果Load一个MAP的时候,则以第一个字段为键,第二个字段为值
var m map[string]string
cnt, err := sess.Select("email, name").From("dbr_people").Load(&m)
require.NoError(t, err)
require.Equal(t, 3, cnt)
require.Len(t, m, 3)
require.Equal(t, "test1", m["[email protected]"])
//当最为一个对象map的时候.则以第一个字段为键,并将除了第一个字段之外的值赋予对象
//即dbrPerson中的id为0
var m2 map[int64]*dbrPerson
cnt, err = sess.Select("id, name, email").From("dbr_people").Load(&m2)
require.NoError(t, err)
require.Equal(t, 3, cnt)
require.Len(t, m2, 3)
require.Equal(t, "[email protected]", m2[1].Email)
require.Equal(t, "test1", m2[1].Name)
// the id value is used as the map key, so it is not hydrated in the struct
require.Equal(t, int64(0), m2[1].Id)
//当以第一个字段作为KEY,第二个字段作为值,当可能作为KEY的字段有重复的时候,
//则将值append到其KEY对应MAP下的[]string中
var m3 map[string][]string
cnt, err = sess.Select("name, email").From("dbr_people").OrderAsc("id").Load(&m3)
require.NoError(t, err)
require.Equal(t, 3, cnt)
require.Len(t, m3, 2)
require.Equal(t, []string{"[email protected]"}, m3["test1"])
require.Equal(t, []string{"[email protected]", "[email protected]"}, m3["test2"])
var set map[string]struct{}
cnt, err = sess.Select("name").From("dbr_people").Load(&set)
require.NoError(t, err)
require.Equal(t, 3, cnt)
require.Len(t, set, 2)
_, ok := set["test1"]
require.True(t, ok)
}
}
Load操作之Slice
type stringSliceWithSQLScanner []string
func (ss *stringSliceWithSQLScanner) Scan(src interface{}) error {
*ss = append(*ss, "called")
return nil
}
func TestSliceWithSQLScannerSelect(t *testing.T) {
for _, sess := range testSession {
reset(t, sess)
_, err := sess.InsertInto("dbr_people").
Columns("name", "email").
Values("test1", "[email protected]").
Values("test2", "[email protected]").
Values("test3", "[email protected]").
Exec()
//传一个基本对象切片到load,则得到所有记录第一个字段的切片,本案例等同于.ReturnStrings()函数
//但是这种操作可以是有支持Scan接口的自定义对象比如[]*decimal.Big{}
//或Return系列函数不支持的类型比如[]Float64{}
//plain string slice (original behavior)
var stringSlice []string
cnt, err := sess.Select("name").From("dbr_people").Load(&stringSlice)
require.NoError(t, err)
require.Equal(t, 3, cnt)
require.Len(t, stringSlice, 3)
//当对象支持Scanner接口时,则会调用对象的Scan方法,并把第一条记录中的第一个字段.传入做解析.
//string slice with sql.Scanner implemented, should act as a single record
var sliceScanner stringSliceWithSQLScanner
cnt, err = sess.Select("name").From("dbr_people").Load(&sliceScanner)
require.NoError(t, err)
require.Equal(t, 1, cnt)
require.Len(t, sliceScanner, 1)
}
}
Load操作之InterfaceLoader 我希望把数据载入到一个[]interface 但是数据加载时还要指定interface的实际结构
func TestInterfaceLoader(t *testing.T) {
for _, sess := range testSession {
reset(t, sess)
_, err := sess.InsertInto("dbr_people").
Columns("name", "email").
Values("test1", "[email protected]").
Values("test2", "[email protected]").
Values("test2", "[email protected]").
Exec()
var m []interface{}
//其中dbrPerson作为解析的结构模板.如果作为结构模板的类型不是一个struct,则会用第一个字段的值去做转换
cnt, err := sess.Select("*").From("dbr_people").Load(InterfaceLoader(&m, dbrPerson{}))
require.NoError(t, err)
require.Equal(t, 3, cnt)
require.Len(t, m, 3)
person, ok := m[0].(dbrPerson)
require.True(t, ok)
require.Equal(t, "test1", person.Name)
}
}