go - 将一片结构保存到 Cloud Datastore(Datastore 模式下的 Firestore)中的正确方法是什么?

标签 go google-cloud-firestore google-cloud-datastore

我想在 Google Cloud Datastore(Datastore 模式下的 Firestore)中保存一部分结构。

以电话簿和联系人为例。

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
}

保存和加载这个结构没有问题,因为 Datastore library照顾好它。

由于我的实际代码中存在一些复杂的属性,我需要实现PropertyLoadSaver方法。

保存 Title 属性很简单。但是我在存储联系人结构的 slice 时遇到了问题。

我尝试使用 SaveStruct 方法:

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
}

此代码编译但不工作。

错误信息是datastore: invalid entity type

显式制作 Property slice 也不起作用:

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
}

制作实体 slice 也不起作用:

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
}

两者都产生了相同的错误 datastore: invalid entity type

最后我求助于使用 JSON。 Contact slice 被转换为 JSON 数组。

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
}

除了使用 JSON 之外,还有更好的方法吗?

最佳答案

我找到了这个 document它提到 src 必须是一个结构指针。

关于go - 将一片结构保存到 Cloud Datastore(Datastore 模式下的 Firestore)中的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57577121/

相关文章:

go - 不解决 vendor 目录中的依赖关系

go - 根据类型断言等返回参数的数量更改行为

go - 在 Go 中解析格式错误的 xml 文件

java - 在 Google 数据存储中使用不完整的 key 调用 get?

google-app-engine - 将查询变成投影查询,节省成本

interface - 模板不会将接口(interface)类型的字段评估为基础类型

firebase - Cloud Firestore上一组对象的数组vs. map vs.子集合

ios - Foreach 如果所有字段都是 "0",返回一个 View

javascript - Cloud Firestore 读/写错误 : The 'Access-Control-Allow-Origin' header has a value 'null'

java - GAE 数据存储 JOIN + GROUP BY