[英]Remove all the records from ets table having datestamp older than 10 seconds
I have an ets
set table in an elixir app. 我在长生不老药应用程序中有一个
ets
set表。 I need to clean-up records which have their updated_at field older than 10 seconds. 我需要清理其update_at字段早于10秒的记录。 Is there a way I can set expiry or do it manually without iterating over all the records?
有没有一种方法可以设置到期时间或手动进行设置而无需遍历所有记录? I match records based on the timestamps greater than given time.
我根据大于给定时间的时间戳匹配记录。
example record: 示例记录:
key: key_1
record: %{id: key_1, updated_at: ~N[2018-12-19 10:08:47.803075]}
so far I have this code 到目前为止,我有此代码
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
If you store the "updated at" time as an integer instead of as a NaiveDateTime
struct, you can use a match spec. 如果将“更新时间”时间存储为整数而不是
NaiveDateTime
结构,则可以使用匹配规范。
For example, to get the current time as the number of seconds since the Unix epoch: 例如,要获取当前时间作为自Unix时代以来的秒数:
> DateTime.to_unix(DateTime.utc_now())
1545215338
You can do something like this: 您可以执行以下操作:
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]
In the call to ets:select_delete/2
, I pass a match specification . 在对
ets:select_delete/2
的调用中,我传递了一个match规范 。 It consists of three parts: 它包括三个部分:
{:_, :"$1"}
, I perform a match on the records in the table. {:_, :"$1"}
,我对表中的记录进行匹配。 In this example, I have a tuple with two elements. :_
, and assign the timestamp to a match variable with :"$1"
. :_
的键,并使用:"$1"
将时间戳分配给匹配变量。 [{:<, :"$1", 1545215144}]
, I specify that I only want to match records with a timestamp before this time. [{:<, :"$1", 1545215144}]
,我指定只希望在此时间之前将记录与时间戳进行匹配。 In your case, you would calculate the time ten seconds in the past and put that value here. [true]
, I specify that I want to return true
for matching records, which in the case of select_delete
means "delete this record". [true]
,我指定要为匹配的记录返回true
,在select_delete
的情况下意味着“删除此记录”。 So after calling select_delete
, only the second record remains in the table. 因此,在调用
select_delete
,仅第二条记录保留在表中。
If the timestamp is inside a map, you can use map_get
to access it and compare it: 如果时间戳在地图内,则可以使用
map_get
进行访问并进行比较:
:ets.select_delete(:foo, [{{:_, :"$1"},
[{:<, {:map_get, :updated_at, :"$1"}, 1545215339}],
[true]}])
Or (in Erlang/OTP 18.0 and later) match out the map value: 或者(在Erlang / OTP 18.0及更高版本中)匹配地图值:
:ets.select_delete(:foo, [{{:_, #{updated_at: :"$1"}},
[{:<, :"$1", 1545215339}],
[true]}])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.