Google 数据存储祖先查询返回的数据太低
Google Datastore ancestor query returning data too far down
我有一个正在开发的 "inbox/messaging" 结构,它允许多种 parent。例如,人们可以对 object 的几个不同 kind
发表评论。对于此示例,假设有人在 Article
object.
上发表评论
按照我们格式化数据的方式,评论创建为 Message
object,而 object 是 child 的 Article
](并且 Article
是 Account
的 child)。因此,当我们查询消息列表时,我们只需要 Article
实例的 children 的所有消息。看起来像这样:
Message.query(ancestor=source_key)
source_key
这是我们正在查看的文章的 Key
。
太棒了,这真的很好用而且速度很快。
现在我们要向那些 Message
object 添加 回复。我认为我们将以与将 Message
添加到 Article
相同的方式存储回复。也就是说,回复只是 Message
的另一个实例,而回复 object 的 parent 就是它正在回复的消息。所以基本上,您不是在文章上发表评论,而是在消息上发表评论。
这在纸面上听起来不错,但在实践中似乎 Key
它最终得到的结构如下:
Key('Account', 5629499534213120, 'Article', 5946158883012608, 'Message', 6509108836433920)
事实证明,当我们查询消息列表时,它 return 回复 也在响应中,就好像它们没有回复全部。
一些问题:
有没有什么方法可以像 "shallow" 查询那样做?要严格地得到只那个Article
?
的直接children
我阅读了更多关于 how ancestor queries 的工作,因为祖先查询有每秒 1 次写入的限制,我现在想知道改变我们存储它的方式是否更好Message
是 而不是 Article
的 child,而是可能存在 Article
的 KeyProperty
在 Message
上,如果这有意义的话。 Message
可能没有 parent。可能有很多人对一篇文章发表评论,或者也有很多人对这些评论留下 回复。但即便如此,Article
也是 Account
的 child,以及许多其他类型的 object,通常我们不会 运行进入许多不同写入的任何问题。那么我们是否会 运行 进入此写入限制?
编辑:我继续前进了一点,我正在尝试查询 仅 给定消息的回复,所以我正在寻找具有 parent 另一条消息的(祖先)。
因此将此密钥作为祖先:Key('Account', 5629499534213120, 'Article', 5946158883012608, 'Message', 5663034638860288)
我查询了我们的消息 table,然后我得到了完全相同的密钥(以及其他消息)。这怎么可能?如果我指定一个祖先,在什么情况下我会返回与我用来查询祖先相同的 object 是有意义的?该消息的 parent 只是:
Key('Account', 5629499534213120, 'Article', 5946158883012608)
所以,很明显祖先在那里并不严格匹配。为什么我的查询会return呢?基本上,我 运行 正在进入的 Hastebin:https://hastebin.com/karojolisi.py
关于写入限制的问题,如果您在Datastore 模式下使用Cloud Firestore,那么每秒1 次写入的限制是按实体而非实体组。
见https://cloud.google.com/datastore/docs/firestore-or-datastore
"Writes to an entity group are no longer limited to 1 per second."
和https://cloud.google.com/datastore/docs/concepts/limits
"Maximum write rate to an entity" 是“每秒 1 个”
因此,无论您采用哪种方法,在数据存储模式下,写入都不应该是一个问题,因为消息和回复预计不会被编辑。当然,除非您有任何类型的聚合信息,例如给定消息的回复数量,这需要用每个子记录更新父消息记录。
关于您只查询文章的消息而不是他们的回复的主要问题,一个选择是有一个名为 article_id 的字段,并且只为顶级消息填充它,并将它也放在索引(祖先复合索引的前缀)。推荐 article_id 而不是布尔值的原因是,因为这个字段是索引的,所以最好不要让这个字段基于一个狭窄的值范围。
之所以更喜欢这种方法而不是将消息存储在单独的 table 中,是因为属于一篇文章的所有消息都将存储在初始方法附近,这对于读取性能更好。
我有一个正在开发的 "inbox/messaging" 结构,它允许多种 parent。例如,人们可以对 object 的几个不同 kind
发表评论。对于此示例,假设有人在 Article
object.
按照我们格式化数据的方式,评论创建为 Message
object,而 object 是 child 的 Article
](并且 Article
是 Account
的 child)。因此,当我们查询消息列表时,我们只需要 Article
实例的 children 的所有消息。看起来像这样:
Message.query(ancestor=source_key)
source_key
这是我们正在查看的文章的 Key
。
太棒了,这真的很好用而且速度很快。
现在我们要向那些 Message
object 添加 回复。我认为我们将以与将 Message
添加到 Article
相同的方式存储回复。也就是说,回复只是 Message
的另一个实例,而回复 object 的 parent 就是它正在回复的消息。所以基本上,您不是在文章上发表评论,而是在消息上发表评论。
这在纸面上听起来不错,但在实践中似乎 Key
它最终得到的结构如下:
Key('Account', 5629499534213120, 'Article', 5946158883012608, 'Message', 6509108836433920)
事实证明,当我们查询消息列表时,它 return 回复 也在响应中,就好像它们没有回复全部。
一些问题:
有没有什么方法可以像 "shallow" 查询那样做?要严格地得到只那个
Article
? 的直接children
我阅读了更多关于 how ancestor queries 的工作,因为祖先查询有每秒 1 次写入的限制,我现在想知道改变我们存储它的方式是否更好
Message
是 而不是Article
的 child,而是可能存在Article
的KeyProperty
在Message
上,如果这有意义的话。Message
可能没有 parent。可能有很多人对一篇文章发表评论,或者也有很多人对这些评论留下 回复。但即便如此,Article
也是Account
的 child,以及许多其他类型的 object,通常我们不会 运行进入许多不同写入的任何问题。那么我们是否会 运行 进入此写入限制?
编辑:我继续前进了一点,我正在尝试查询 仅 给定消息的回复,所以我正在寻找具有 parent 另一条消息的(祖先)。
因此将此密钥作为祖先:Key('Account', 5629499534213120, 'Article', 5946158883012608, 'Message', 5663034638860288)
我查询了我们的消息 table,然后我得到了完全相同的密钥(以及其他消息)。这怎么可能?如果我指定一个祖先,在什么情况下我会返回与我用来查询祖先相同的 object 是有意义的?该消息的 parent 只是:
Key('Account', 5629499534213120, 'Article', 5946158883012608)
所以,很明显祖先在那里并不严格匹配。为什么我的查询会return呢?基本上,我 运行 正在进入的 Hastebin:https://hastebin.com/karojolisi.py
关于写入限制的问题,如果您在Datastore 模式下使用Cloud Firestore,那么每秒1 次写入的限制是按实体而非实体组。
见https://cloud.google.com/datastore/docs/firestore-or-datastore
"Writes to an entity group are no longer limited to 1 per second."
和https://cloud.google.com/datastore/docs/concepts/limits
"Maximum write rate to an entity" 是“每秒 1 个”
因此,无论您采用哪种方法,在数据存储模式下,写入都不应该是一个问题,因为消息和回复预计不会被编辑。当然,除非您有任何类型的聚合信息,例如给定消息的回复数量,这需要用每个子记录更新父消息记录。
关于您只查询文章的消息而不是他们的回复的主要问题,一个选择是有一个名为 article_id 的字段,并且只为顶级消息填充它,并将它也放在索引(祖先复合索引的前缀)。推荐 article_id 而不是布尔值的原因是,因为这个字段是索引的,所以最好不要让这个字段基于一个狭窄的值范围。
之所以更喜欢这种方法而不是将消息存储在单独的 table 中,是因为属于一篇文章的所有消息都将存储在初始方法附近,这对于读取性能更好。