dongqiangse6623 2019-08-20 15:36
浏览 138

将切片结构保存到Cloud Datastore(数据存储模式下的Firestore)的正确方法是什么?

I want to save a slice of structs in Google Cloud Datastore (Firestore in Datastore mode).

Take this Phonebook and Contact for example.

type Contact struct {
  Key         *datastore.Key `json:"id" datastore:"__key__"`
  Email       string         `json:"email" datastore:",noindex"`
  Name        string         `json:"name" datastore:",noindex"`
}
type Phonebook struct {
  Contacts []Contact
  Title    string
}

Saving and loading this struct is no problem as the Datastore library takes care of it.

Due to the presence of some complex properties in my actual code, I need to implement PropertyLoadSaver methods.

Saving the Title property is straightforward. But I have problems storing the slice of Contact structs.

I tried using the SaveStruct method:

func (pb *Phonebook) Save() ([]datastore.Property, error) {
  ps := []datastore.Property{
    {
      Name:    "Title",
      Value:   pb.Title,
      NoIndex: true,
    },
  }
  ctt, err := datastore.SaveStruct(pb.Contacts)
  if err != nil {
    return nil, err
  }
  ps = append(ps, datastore.Property{
    Name:    "Contacts",
    Value:   ctt,
    NoIndex: true,
  })

  return ps, nil
}

This code compiles but doesn't work.

The error message is datastore: invalid entity type

Making a slice of Property explicitly also does not work:

func (pb *Phonebook) Save() ([]datastore.Property, error) {
  ps := []datastore.Property{
    {
      Name:    "Title",
      Value:   pb.Title,
      NoIndex: true,
    },
  }
  cttProps := datastore.Property{
    Name:    "Contacts",
    NoIndex: true,
  }
  if len(pb.Contacts) > 0 {
    props := make([]interface{}, 0, len(pb.Contacts))
    for _, contact := range pb.Contacts {
      ctt, err := datastore.SaveStruct(contact)
      if err != nil {
        return nil, err
      }
      props = append(props, ctt)
    }
    cttProps.Value = props
  }
  ps = append(ps, cttProps)

  return ps, nil
}

Making a slice of Entity does not work either:

func (pb *Phonebook) Save() ([]datastore.Property, error) {
  ps := []datastore.Property{
    {
      Name:    "Title",
      Value:   pb.Title,
      NoIndex: true,
    },
  }
  cttProps := datastore.Property{
    Name:    "Contacts",
    NoIndex: true,
  }
  if len(pb.Contacts) > 0 {
    values := make([]datastore.Entity, len(pb.Contacts))
    props := make([]interface{}, 0, len(pb.Contacts))
    for _, contact := range pb.Contacts {
      ctt, err := datastore.SaveStruct(contact)
      if err != nil {
        return nil, err
      }
      values = append(values, datastore.Entity{
        Properties: ctt,
      })
    }
    for _, v := range values {
      props = append(props, v)
    }
    cttProps.Value = props
  }
  ps = append(ps, cttProps)

  return ps, nil
}

Both yielded the same error datastore: invalid entity type

Finally I resorted to using JSON. The slice of Contact is converted into a JSON array.

func (pb *Phonebook) Save() ([]datastore.Property, error) {
  ps := []datastore.Property{
    {
      Name:    "Title",
      Value:   pb.Title,
      NoIndex: true,
    },
  }
  var values []byte
  if len(pb.Contacts) > 0 {
    js, err := json.Marshal(pb.Contacts)
    if err != nil {
      return nil, err
    }
    values = js
  }
  ps = append(ps, datastore.Property{
    Name:    "Contacts",
    Value:   values,
    NoIndex: true,
  })

  return ps, nil
}

Isn't there a better way of doing this other than using JSON?

  • 写回答

2条回答 默认 最新

  • drxp993551 2019-08-21 13:45
    关注

    I found this document and it mentions src must be a struct pointer.

    评论

报告相同问题?

悬赏问题

  • ¥50 永磁型步进电机PID算法
  • ¥15 sqlite 附加(attach database)加密数据库时,返回26是什么原因呢?
  • ¥88 找成都本地经验丰富懂小程序开发的技术大咖
  • ¥15 如何处理复杂数据表格的除法运算
  • ¥15 如何用stc8h1k08的片子做485数据透传的功能?(关键词-串口)
  • ¥15 有兄弟姐妹会用word插图功能制作类似citespace的图片吗?
  • ¥200 uniapp长期运行卡死问题解决
  • ¥15 latex怎么处理论文引理引用参考文献
  • ¥15 请教:如何用postman调用本地虚拟机区块链接上的合约?
  • ¥15 为什么使用javacv转封装rtsp为rtmp时出现如下问题:[h264 @ 000000004faf7500]no frame?