dtcd27183 2014-07-11 09:22
浏览 48

用单个表将数组/结构中的多列绑定

I would like to use an orm. I looked at here to find some orms with documentations. The problem I'm facing is that none of those orms seems to be able to bind multiple columns into an array or a sub-structure.

To be clear, here is an example. I have a table that looks like that :

Table User
----------
UserId
UserName
UserPositionX
UserPositionY
UserPositionZ

Ideally, I would like to bind the fields into this structure (The array is to be coherent with another API that I'm using client-side) :

type User struct {
    Id int64
    Name string
    Position [3]float64
}

Where UserPositionX binds to Position[0], UserPositionY binds to Position[1] and UserPositionZ binds to Position[2].

I'm open to use a structure like this one instead of an array :

type Vector3 struct {
    X, Y, Z float64
}

type User struct {
    Id int64
    Name string
    Position Vector3
}

But then I'm facing two problems :

  • I don't want to separate the Position fields in another table. All orms that I looked seems to consider that 1 struct = 1 table.
  • This structure have to be converted (marshalled) into json. In this json, I need the position to be an array (example : {"id": 42, name: "Foo", position: [6.3, 8.6, 2.65]}).

So my question is : Is there an available orm for go (and sqlite) that is capable of binding multiple columns in an array or struct without creating another table ? If it's not possible with an array, is there a way to customize how a specific type is marshalled into json ?


EDIT

I found a way to change how a specific type is converted into json. I just need to add two methods to the given type. In this example :

func (p *Vector3) MarshalJSON() ([]byte, error) {
    return []byte(fmt.Sprintf("[%v,%v,%v]", p.X, p.Y, p.Z)), nil
}

func (p *Vector3) UnmarshalJSON(data []byte) (err error) {
    _, err = fmt.Sscanf(string(data), "[%v,%v,%v]", &p.X, &p.Y, &p.Z)
    return
}

Result :

test, _ := json.Marshal(User{3, "fooBarBaz", Vector3{42.0, 35, 23.45}})
fmt.Println(string(test))
// ==> {"Id":3,"Name":"fooBarBaz","Position":[42.0,35,23.45]}

test2 := User{}
json.Unmarshal([]byte(`{"Id":3,"Name":"fooBarBaz","Position":[42.0,35,23.45]}`), &test2)
log.Println(test2)
// ==> {3 fooBarBaz {42.0 35 23.45}}

My initial problem still exists because I tested some orms in the list and the only thing I found is by embedding structs, and I need the Vector3 to be an attribute.

  • 写回答

1条回答 默认 最新

  • dongtun3259 2014-12-09 11:14
    关注

    in this case you need to combine to features of the database/sql package and the sql database:

    1. You need to group your position columns with GROUP_CONCAT to a comma separated list.
    2. You need to implement the sql.Scanner interface on your type to map the comma separated list to an array.

    For the first step you can look at existing questions.

    For the second step you could use something like:

    type Foo struct {
        Bar []string
    }
    
    func (f *Foo) Scan(src interface{}) error {
        switch t := src.(type) {
        // t would then equal "value1, value2, value3"
        case string:
            *f = strings.Split(t, ",")
    
            return nil
        }
    
        return ErrBadScanType
    }
    

    Example where mapping key1:value1, key2:value2, ... to an object.

    PS: You should also consider using some special geo data type for storing vectors if supported by your database.

    评论

报告相同问题?

悬赏问题

  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?
  • ¥15 matlab(相关搜索:紧聚焦)
  • ¥15 基于51单片机的厨房煤气泄露检测报警系统设计
  • ¥15 Arduino无法同时连接多个hx711模块,如何解决?
  • ¥50 需求一个up主付费课程
  • ¥20 模型在y分布之外的数据上预测能力不好如何解决