从 ets 表中删除日期戳超过 10 秒的所有记录

Posted

技术标签:

【中文标题】从 ets 表中删除日期戳超过 10 秒的所有记录【英文标题】:Remove all the records from ets table having datestamp older than 10 seconds 【发布时间】:2019-05-19 19:31:02 【问题描述】:

我在 elixir 应用程序中有一个 ets 设置表。我需要清理其 updated_at 字段超过 10 秒的记录。有没有一种方法可以设置到期时间或手动执行而不遍历所有记录?我根据大于给定时间的时间戳匹配记录。

示例记录:

key: key_1
record: %id: key_1, updated_at: ~N[2018-12-19 10:08:47.803075]

到目前为止我有这个代码

def clean_stale(previous_key) do
  if previous_key == :"$end_of_table" do
    :ok
  else
    device = get(previous_key)
    next_key = :ets.next(__MODULE__, previous_key)
    if NaiveDateTime.diff(NaiveDateTime.utc_now, device.last_recorded_at) > 10 do
      remove(device.id)
    end
    clean_stale(next_key)
  end
end

【问题讨论】:

你试过查看advanced lookup吗?即使用:ets.fun2ms/1派生一个可以为您进行比较的函数? 谢谢@matov。我想我得到了完整的答案。是的,我有。但由于我是新手并没有从中得到太多 【参考方案1】:

如果将“更新时间”存储为整数而不是 NaiveDateTime 结构,则可以使用匹配规范。

例如,获取当前时间作为自 Unix 纪元以来的秒数:

> DateTime.to_unix(DateTime.utc_now())
1545215338

你可以这样做:

iex(3)> :ets.new(:foo, [:public, :named_table])
:foo
iex(4)> :ets.insert(:foo, :key1, DateTime.to_unix(DateTime.utc_now()))
true
iex(5)> :ets.insert(:foo, :key2, DateTime.to_unix(DateTime.utc_now()))
true
iex(6)> :ets.tab2list(:foo)
[key2: 1545215144, key1: 1545215140]
iex(7)> :ets.select_delete(:foo, [:_, :"$1", [:<, :"$1", 1545215144], [true]])
1
iex(8)> :ets.tab2list(:foo)
[key2: 1545215144]

在对ets:select_delete/2 的调用中,我传递了一个match specification。它由三部分组成:

使用:_, :"$1",我对表中的记录执行匹配。在这个例子中,我有一个包含两个元素的元组。我忽略了带有:_ 的键,并将时间戳分配给带有:"$1" 的匹配变量。 使用[:&lt;, :"$1", 1545215144],我指定我只想匹配具有此时间之前的时间戳的记录。在您的情况下,您将计算过去十秒的时间并将该值放在这里。 使用[true],我指定要返回true 以匹配记录,在select_delete 的情况下,这意味着“删除此记录”。

所以调用select_delete后,表中只剩下第二条记录了。


如果时间戳在地图内,你可以使用map_get来访问它并进行比较:

:ets.select_delete(:foo, [:_, :"$1",
                           [:<, :map_get, :updated_at, :"$1", 1545215339],
                           [true]])

或者(在 Erlang/OTP 18.0 及更高版本中)匹配映射值:

:ets.select_delete(:foo, [:_, #updated_at: :"$1",
                           [:<, :"$1", 1545215339],
                           [true]])

【讨论】:

但在我的情况下,值是地图。如果 value 只是一个时间戳,那么在我的情况下它没有用。 我更新了答案以从地图内部获取时间戳

以上是关于从 ets 表中删除日期戳超过 10 秒的所有记录的主要内容,如果未能解决你的问题,请参考以下文章

通过从 SQL Server 中的当前日期删除超过 180 天的所有记录来清除

如何在时间戳字段中仅使用日期来选择记录?

Oracle:有效地使用where子句过滤时间戳列以获取特定日期的所有记录

从 netezza 表中清除记录

从熊猫数据框中的日期时间中删除时间戳

MySQL - 当时间戳是日期的一部分时,如何查找昨天的记录