我们正在设计的应用程序具有一个功能,用户可以动态地将新元素添加到实体中,然后需要有效地搜索该实体。这些元素的数量基本上是无限的。我们的团队一直将 DynamoDB 视为一种数据存储选项,并且一直在研究键/值模型以及如何在索引下获取动态数据以进行高效查询。
我认为我有一个单表解决方案,可以优雅地处理问题,并且还允许查询数据存储中的任何给定属性,但我很不安,因为我找不到以下示例它在其他任何地方。希望它在某些方面没有根本性的缺陷 - 我将不胜感激任何批评!
该模型本质上是 Entity-Attribute-Value用于向 RDBM 添加动态或稀疏数据的方法。因此,不要像这样在 DynamoDB 表中存储不同的实体/对象:
PK SK SK-1 SK-2 SK-3 SK-N... PK SK SK-1 SK-N...
Key Key Key Key --> Name Money
Entity Id Value Value Value Value Person 22 Fred 30000
...这让我可以查询诸如“name = Fred的所有人”之类的内容,但是您最终会用完排序键索引,并且您需要在查询之前知道哪个索引与哪个键对应,数据可以以 EAV 格式存储,如下所示:
PK SK & GSI-PK GSI-SK PK SK & GSI-PK GSI-SK
Id Entity#Key Value 22 Person#Name Fred
Id Entity#Key Value --> 22 Person#Money 30000
Id Entity#Key Value 22 Person#Sex M
Id Entity#Key Value 22 Person#DOB 09/00
现在,通过一个全局二级索引(Entity.Key 上的 GSI-1 PK 和 Value 上的 GSI-1 SK),我可以对任何键的任何值进行范围搜索,并获取匹配的 Id 列表。用户可以添加他们的属性甚至全新的实体,并以立即索引的方式保留它们,而无需我们修改 DynamoDB 架构。
我能想到的这种方法的一个主要缺点是,从 Entity#Key-Value 查询返回的数据仅包含该键和实体 Id 的值,而不是整个实体。这对于图表和图形来说很好,但如果您想通过一个查询获得网格类型的结果,那就是一个问题。我还担心索引上的热分区键,但希望我们可以通过智能写入分片来解决这个问题。
差不多就这些了。通过一些调整,可以扩展模型以支持记录每个键上的所有更改,并允许针对这些更改进行一些不错的时间序列查询,但我的问题是是否有人发现对 KV 存储采用 EAV 类型方法很有用例如 DynamoDB,或者是否有其他方法来处理动态架构查询?
最佳答案
您可以将 pk 作为实体的 id
。然后是排序键 {attributeName}。您可能仍然希望拥有带有诸如createdAt等字段的基本实体。
所以你可能有:
PK SORT Attributes:
#Entity#22 #Entity#Details createdAt=2020
#Entity#22 #Attribute#name key=name value=Fred
#Entity#22 #Attribute#money key=money value=30000
要获取实体的所有属性,您只需执行不带 pk={id}
过滤器的查询。您无法按每个给定属性动态排序,这正是 DynamoDB 不擅长的,我重复一遍!这种情况正是 NOSQL 表现不佳的地方。
你可以做的是使用流式传输来进行聚合。例如,您可以存储前 10 位最富有的人:
PK SORT Attributes:
#Money#Highest #1 id=#Entity#22 value=30000
#Money#Highest #2 id=#Entity#52 value=30000
您将在 DynamoDB Streams 中进行计算。但是您无法动态索引值,DynamoDB 的工作原理是有效地将数据从一种表单复制到另一种表单,以便可以有效地检索数据。因此,您将复制您想要搜索的每个新属性的整个数据库,否则您将不得不使用扫描,而这样做没有任何意义,因为如果您所做的一切都不会从使用 DynamoDB 中获得任何好处一直在进行扫描。
您需要很好地理解您的流程才能充分利用 DynamoDb,如果您想随意索引数据并执行各种不同的查询,您可能需要 SQL 数据库或 elasticsearch。
关于nosql - 支持对任何给定属性进行查询的 DynamoDB 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61836423/