【问题标题】:Storing user data in Google Cloud Datastore as an Entity Group将用户数据作为实体组存储在 Google Cloud Datastore 中
【发布时间】:2018-11-22 10:02:56
【问题描述】:

我正在尝试找到将用户存储在谷歌数据存储中的最佳方式(使用 nodejs)。我有 userId 和一个 userData 对象:

userId: "some-random-string"

userData: {
    info: {
        name: "name",
        email: "test@email.com"
    },
    profile: {
        username: "user",
        status: "using"
    },
    stats: {
        stuffDone: 12,
        stuffNotDone: 20
    },
    inventory: {
        money: 100,
        items: ["first", "second", "third"]
    }
}

我知道我可以将所有这些存储为单个实体,但如果我将分别更新所有嵌套对象(信息、配置文件、统计信息、库存),是否值得将其拆分为一个实体组。

所以我将拥有根实体(可能不存在):

datastore.key(["Users", userId])

然后我会创建 4 个孩子来存储 userData:

datastore.key(["Users", userId, "UserData", "Info"); --> userData.info
datastore.key(["Users", userId, "UserData", "Profile"); --> userData.profile
datastore.key(["Users", userId, "UserData", "Stats"); --> userData.stats
datastore.key(["Users", userId, "UserData", "Inventory"); --> userData.inventory

只有用户会更新数据,所以争用应该不是问题。创建用户后,我一次不需要更新多个孩子。

所以说统计数据每分钟更新一次,我可以直接用密钥更新它:

datastore.key(["Users", userId, "UserData", "Stats");

这是将其拆分而不是将整个用户对象重写为单个实体并必须重写所有索引的最佳做法吗?


使用实体组,我仍然可以一次查询所有用户数据:

query = datastore.createQuery().hasAncestor(datastore.key(["Users", userId]));

然后我只需要对其进行处理以将其返回到上面的 userData 对象中。我只需要在用户登录时执行一次,所有其他时间我都需要获取用户数据,它只是一个孩子,我可以通过密钥获取孩子。


如果我不应该使用这样的实体组,那么我可以通过将用户的每个部分存储在单独的实体中来做同样的事情,例如:

datastore.key(["UsersInfo", userId); --> userData.info
datastore.key(["UsersProfile", userId); --> userData.profile
datastore.key(["UsersStats", userId); --> userData.stats
datastore.key(["UsersInventory", userId); --> userData.inventory

然后我仍然可以单独更新它们,但我认为获取所有数据会更费力,因为我需要执行 4 次查询而不是祖先查询。


如果我每分钟只更新一次 userData.stats 和 userData.profile,或者我应该只使用一个实体,是否需要这些实体组或多个实体。 stats 和 profile 对象将变得比几个属性更大。

【问题讨论】:

    标签: node.js google-app-engine google-cloud-platform google-cloud-datastore


    【解决方案1】:

    根据属性更新模式将实体拆分为多个相关的实体可能是一个好主意,尤其是对于大型实体 - 以避免在实体的一部分发生更改时不必要地重写整个实体(伴随着相关的增加实体本身及其所有相关索引的更新持续时间。请参阅相关re-using an entity's ID for other entities of different kinds - sane idea?

    将所有实体“片段”放入同一个实体组 - 正如您所观察到的,这允许您进行祖先查询以检索用户数据,只要您尊重每个整个实体的最大 1 次写入/秒,就可以了团体。只需仔细检查您是否可以安全地假设查询结果按特定顺序出现,否则您可能需要采取措施确保每个结果都发送到正确的对象。

    使用单独的、非祖先相关的实体“片段”允许比使用祖先分割更高的整体写入速率:每个实体最多 1 次写入/秒。从技术上讲,您不需要执行 4 个 查询 来检索实体,而是需要执行 4 个关键 lookup 操作,请参阅Retrieving an entity

    但是拆分实体也会增加您的数据存储成本:单个实体的单个读/写操作将乘以拆分实体的“片段”数 - 如果您读/写,则在您的情况下为 4所有这些都在一起。

    因此,您必须在应用程序的上下文中平衡这些利弊。

    【讨论】:

      猜你喜欢
      • 2014-07-30
      • 1970-01-01
      • 2018-07-27
      • 1970-01-01
      • 2016-10-08
      • 1970-01-01
      • 1970-01-01
      • 2017-05-07
      • 2020-05-05
      相关资源
      最近更新 更多