user3644708
user3644708

Reputation: 2495

Erlang ets remove / filter element

I use elang ets table as a simple cache. I want to use a process to scan the table and remove expired elements (multiple).

with ets:foldl

expire_table_example() ->
Tab = ets:new(ets_tab, [named_table, set]),
ets:insert(Tab, [{a, 1}, {b, 2}, {c, 3}, {d, 4}, {e, 5},{f,7}]),
Tab1 = ets:foldl(fun({Key, Val}, Acc) ->
if
   (Val > 3) -> [{Key, Val} | Acc];
   true -> Acc
 end
end, Tab, Tab),
io:format("end ~p ~n", [Tab1]).

I got

[{f,7},{e,5},{d,4}|ets_tab] %% the ets_tab is NOT expected.

How Can I fix This?

Any other API's would do this better?

Upvotes: 4

Views: 1265

Answers (3)

danechkin
danechkin

Reputation: 1306

You may find that deleting huge numbers of objects periodically may result in undesirable latency spikes. There is interesting project which have cache segments as separate ets tables and deletes outdated objects by dropping whole ets, maybe you will find it interesting as well

https://github.com/fogfish/cache

Upvotes: 0

P_A
P_A

Reputation: 1818

You can't use ets table as accumulator.

For your purpose you can use ets:select_delete/2:

1> Tab = ets:new(ets_tab, [named_table, set]).
ets_tab
2> ets:insert(Tab, [{a, 1}, {b, 2}, {c, 3}, {d, 4}, {e, 5},{f,7}]).
true
3> ets:select_delete(Tab, [{{'$1','$2'},[{'=<','$2',3}],[true]}]).
3
4> ets:tab2list(Tab).
[{f,7},{e,5},{d,4}]

Or you can use ets:tab2list/1 to get list of all values, filter them and after that re-insert to table:

1> Tab = ets:new(ets_tab, [named_table, set]).
ets_tab
2> ets:insert(Tab, [{a, 1}, {b, 2}, {c, 3}, {d, 4}, {e, 5},{f,7}]).
true
3> L = ets:tab2list(Tab).
[{f,7},{e,5},{d,4},{c,3},{b,2},{a,1}]
4> L2 = lists:filter(fun({Key,Val}) -> Val > 3 end, L).
[{f,7},{e,5},{d,4}]
5> ets:delete_all_objects(Tab).
true
6> ets:insert(Tab, L2).
true
7> ets:tab2list(Tab).
[{f,7},{e,5},{d,4}]

Upvotes: 6

liam_g
liam_g

Reputation: 311

Another way it can be done is by using list comprehensions.

1> Tab = ets:new(ets_tab, [named_table, set]).
ets_tab   
2> ets:insert(Tab, [{a, 1}, {b, 2}, {c, 3}, {d, 4}, {e, 5},{f,7}]).    
true    
3> [{X,Y} || {X,Y} <- ets:tab2list(Tab), Y>3].    
[{f,7},{e,5},{d,4}]

Upvotes: 0

Related Questions