我的表是(device, type, value, timestamp)
的,其中(device,type,timestamp)
进行唯一的组合(非DynamoDB DBMS中组合键的候选者(。
我的查询范围可以在这三个属性中的任何一个之间,例如
从(device
(获取(value
(的(type
(大于(timestamp
(大于<some-timestamp
>
我正在使用dynamoosejs/dynamoose。从大多数搜索中,我相信我应该使用三个字段的组合(作为单个字段;device-type-timestamp
( 作为id
.但是,Schema
的set: function
不允许我使用对象属性(例如this.device
(,并且由于某些原因,我无法在外部执行此操作。
我得到的最接近 (id:uuidv4:hashKey, device:string:GlobalSecIndex, type:string:LocalSecIndex, timestamp:Date:LocalSecIndex
(
和
(id:uuidv4:rangeKey, device:string:hashKey, type:string:LocalSecIndex, timestamp:Date:LocalSecIndex
(
等等..
但是,在使用查询时,由于场景中缺少id
(hashKey
或rangeKey
(,因此很难获取特定device,type
的结果。
所以问题来了。你会怎么做这样的桌子?
需要注意的是,此表旨在从物联网设备收集内容,每个设备平均每 5 分钟生成一次内容。
我很好奇您为什么选择 DynamoDB 来完成此任务。像这样的高级查询似乎更适合基于SQL的数据库,而不是NoSQL数据库。由于SQL查询的高级性质,根据我的经验,这项任务在SQL数据库中要容易得多。因此,我鼓励您考虑一下 DynamoDB 是否真的适合您在这里尝试执行的操作。
如果您确定是,则可能需要稍微重构数据。您可以执行一些操作,例如拥有一个device-type
的属性,该属性将是设备和类型值的组合。然后将其设置为索引,并基于该索引进行查询并按时间戳排序,并筛选出不大于所需值的结果。
您是正确的,目前,Dynamoose 不会将整个对象传递到set
函数中。这是我个人愿意探索的事情。我是 GitHub 项目的成员,如果您想提交添加该功能的 PR,我将非常乐意与您一起探索该选项并将其放入代码库中。
您可能想要探索的另一件事是拥有一个 DynamoDB 流,每当该流添加到您的 DynamoDB 表时,该流都会设置该device-type
属性。这会将该逻辑从 DynamoDB 和您的应用程序中抽象出来。我不确定你正在做的事情是否有必要将其解耦到那个水平,但它可能是你想要探索的东西。
最后,根据您的设置,您可以确定哪个项将更独特、device
或type
,并在该属性上设置索引。然后,只需基于此进行查询,并筛选出您不需要的其他属性的结果。我不确定这是否是您要找的,它当然会起作用,但我不确定您的表中会有多少项目,并且在某些级别上存在有关可扩展性的问题。解决其中一些可伸缩性问题的一种方法可能是,如果您知道要查询的时间戳是恒定的或提前可预测的,则设置项目的TTL
。
总的来说,有很多方法可以实现您想要做的事情。如果没有更多关于有多少项、这些属性将执行什么操作、所需的可伸缩性量、哪些属性最独特等的详细信息,就很难给出一个好的解决方案。我强烈建议您考虑一下NoSQL是否真的是最好的方法。您要执行的查询似乎更像是SQL查询。并不是说这在 DynamoDB 中是不可能的,但它需要考虑如何构建数据模型等。
考虑到@charlie鱼的意见,我决定跳入Dynamoose
并即兴编写代码,将模型传递给属性的set
函数。但是,我发现model
已经传递给属性default
参数。所以我将Schema
更改为以下内容:
id:hashKey;default: function(model){ return model.device + "" + model.type; }
timestamp:rangeKey
对于任何登陆此答案的人,请注意,default
&set
函数可以使用this
访问属性选项和架构实例。但是,这两个函数都应该是常规函数,而不是箭头函数。
在这里保留这个作为答案,但我在一段时间内不会接受它作为我问题的答案,因为我想等待其他人提出更好的方法。 我还想确保如果为id
字段传递了一个值,则不应设置该值。为此,我可以使用set
忽略实际的传入值,到目前为止,我还不知道如何。