首页 > 后端开发 > Golang > 正文

更新 Datastore 实体:如何在不改变实体键的情况下修改祖先

DDD
发布: 2025-09-15 17:32:01
原创
911人浏览过

更新 datastore 实体:如何在不改变实体键的情况下修改祖先

在 Google Cloud Datastore 中,实体的键(Key)是其唯一标识符。键的组成部分包括种类(Kind)、名称或 ID,以及祖先路径(Ancestor Path)。祖先路径定义了实体在数据层级结构中的位置。因此,无法直接在不改变实体键的情况下修改实体的祖先,因为祖先是键的一部分。

如果尝试更改实体的祖先,实际上是在创建一个新的实体,而原始实体仍然存在。这可能会导致数据不一致或其他问题,特别是在现有代码中已经使用旧键引用的情况下。

替代方案:使用属性而非实体组

如果你的应用场景允许,可以考虑避免使用实体组,并采用以下替代方案:

  1. 在实体中添加属性来表示层级关系。 例如,对于 Company/Department/Employee 这种层级结构,可以在 Employee 实体中添加 Company 和 Department 属性。
type Employee struct {
    Company    string `datastore:"company"`
    Department string `datastore:"department"`
    Name       string `datastore:"name"`
}
登录后复制
  1. 使用属性进行查询。 即使没有实体组,你仍然可以通过这些属性进行查询。
q := datastore.NewQuery("Employee").
    Filter("company =", "MyCompany").
    Filter("department =", "MyDepartment")

var employees []*Employee
keys, err := client.GetAll(ctx, q, &employees)
if err != nil {
    // Handle error
}
登录后复制

示例代码

以下是一个完整的示例,展示了如何使用属性来模拟层级关系:

package main

import (
    "context"
    "fmt"
    "log"
    "os"

    "cloud.google.com/go/datastore"
)

type Employee struct {
    Company    string `datastore:"company"`
    Department string `datastore:"department"`
    Name       string `datastore:"name"`
}

func main() {
    ctx := context.Background()

    // Replace "your-project-id" with your actual Google Cloud project ID.
    projectID := os.Getenv("GOOGLE_CLOUD_PROJECT")
    if projectID == "" {
        log.Fatalf("GOOGLE_CLOUD_PROJECT environment variable must be set.")
    }

    client, err := datastore.NewClient(ctx, projectID)
    if err != nil {
        log.Fatalf("Failed to create client: %v", err)
    }
    defer client.Close()

    // Create a new Employee entity.
    employee := &Employee{
        Company:    "MyCompany",
        Department: "MyDepartment",
        Name:       "John Doe",
    }

    // Create a key for the entity.
    key := datastore.NameKey("Employee", "john.doe", nil)

    // Save the entity to Datastore.
    _, err = client.Put(ctx, key, employee)
    if err != nil {
        log.Fatalf("Failed to save employee: %v", err)
    }

    fmt.Println("Employee saved successfully.")

    // Query for the employee.
    q := datastore.NewQuery("Employee").
        Filter("company =", "MyCompany").
        Filter("department =", "MyDepartment").
        Filter("name =", "John Doe")

    var employees []*Employee
    keys, err := client.GetAll(ctx, q, &employees)
    if err != nil {
        log.Fatalf("Failed to query employees: %v", err)
    }

    if len(employees) > 0 {
        fmt.Printf("Found employee: %+v, key: %+v\n", employees[0], keys[0])
    } else {
        fmt.Println("Employee not found.")
    }
}
登录后复制

注意事项:

AssemblyAI
AssemblyAI

转录和理解语音的AI模型

AssemblyAI 65
查看详情 AssemblyAI
  • 确保已设置 GOOGLE_CLOUD_PROJECT 环境变量
  • 将 datastore:"company" 等标签添加到结构体字段,以便 Datastore 知道如何将数据映射到实体。
  • 使用 datastore.NameKey 创建具有名称的键,或使用 datastore.IDKey 创建具有 ID 的键。

强一致性与最终一致性

使用属性进行查询时,需要注意数据一致性。Datastore 查询通常是最终一致的,这意味着在属性更新后,可能需要几秒钟的时间才能反映在查询结果中。

如果需要强一致性,可以通过键直接查找实体。按键查找始终返回最新的版本。

// Get the employee by key.
var employee Employee
err = client.Get(ctx, key, &employee)
if err != nil {
    log.Fatalf("Failed to get employee by key: %v", err)
}

fmt.Printf("Employee retrieved by key: %+v\n", employee)
登录后复制

总结

虽然无法直接修改 Datastore 实体的祖先而不改变其键,但通过在实体中添加属性来表示层级关系,可以有效避免实体组带来的限制,并提供更灵活的数据管理方式。在选择方案时,请根据你的应用场景和对数据一致性的要求进行权衡。如果需要强一致性,请使用键直接查找实体。

以上就是更新 Datastore 实体:如何在不改变实体键的情况下修改祖先的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号