查询使用元组键的erlang ETS表

查询使用元组键的erlang ETS表,erlang,record,otp,ets,Erlang,Record,Otp,Ets,我有一个ETS表,其中键由{shell,TIME,NAME,ID}之类的记录组成,我希望允许用户使用这些记录的组合来搜索条目。 IE:在哪里 时间高_值 或 时间 结果=ets:select(附表第1行,ets:fun2ms( 乐趣(A=#活动{shell=ActivityShell,活动_data=S1Data}) 何时(活动外壳#活动外壳.tschedTstart)-> 活动壳 完),, 编辑: 到目前为止,我正试图做到这一点: 我有一个记录,我想默认为: -记录(s1shell_查询

我有一个ETS表,其中键由{shell,TIME,NAME,ID}之类的记录组成,我希望允许用户使用这些记录的组合来搜索条目。 IE:在哪里

  • 时间<低_值和时间>高_值 或
  • 时间<40且名称=“SAM” 或
  • ID==123
我了解如何使用fun2ms,但还不足以知道是否有干净的单行程序方法可以做到这一点。我当前的解决方案是将一个搜索请求与6种可能的搜索类型组合相匹配,与我所有其他广泛使用模式匹配的erlang代码相比,它感觉很脏

你们能帮我更智能地使用fun2ms或ETS表格吗?我很确定这个查询只需一行就可以完成。下面是我用来向您展示我拥有的6个函数之一的示例:

  getShells_by_Time(Tstart, Tend) ->
  Results = ets:select(schedule_row1,ets:fun2ms(
    fun(A = #activity{shell = ActivityShell,activity_data = S1Data})
      when (ActivityShell#activity_shell.tsched < Tend)
      andalso (ActivityShell#activity_shell.tsched > Tstart)  ->
      ActivityShell
    end)),
getshell\u按时间(Tstart,Tend)->
结果=ets:select(附表第1行,ets:fun2ms(
乐趣(A=#活动{shell=ActivityShell,活动_data=S1Data})
何时(活动外壳#活动外壳.tschedTstart)->
活动壳
完),,

编辑:

到目前为止,我正试图做到这一点:

我有一个记录,我想默认为: -记录(s1shell_查询,{tsched={u ScLow,{u ScHigh},id=\u id,type=\u type})

这意味着用户可以更改他们想要匹配的任何记录项。问题是不能在记录中默认使用未绑定变量

我的match spec函数如下所示:

    {ScLow,ScHigh} = ShellQuery#s3shell_query.tsched,
  ets:select(Table, ets:fun2ms(
    fun(#stage3Activity{shell = #activity_shell{tsched = Tsched, id = ID, type = Type}})
      when Tsched < ScLow, Tsched>ScHigh,ID == ID, Type == Type ->
      #activity_shell{tsched = Tsched,id = ID,type = Type}
    end)).
{ScLow,ScHigh}=shell查询#s3shell_query.tsched,
ets:选择(表格,ets:fun2ms(
乐趣(#stage3Activity{shell=#activity#u shell{tsched=tsched,id=id,type=type})
当TschedScHigh,ID==ID,Type==Type->
#活动\u外壳{tsched=tsched,id=id,type=type}
(完)。

因此,我一直在试图找出如何忽略用户没有放入shell查询记录中的匹配内容。

您可以使用自定义的匹配规格保护进行搜索,而不是使用
ets:fun2ms/1
,例如:

-module(match_spec_guards).
-export([new/0, populate/0, search/1]).

-record(row, {
          key :: {shell, Time :: integer(), Name :: string(), ID :: term()},
          value :: term()
         }).

new() ->
    ets:new(?MODULE, [set, named_table, {keypos, #row.key}]).

populate() ->
    [ets:insert(?MODULE, #row{key = {shell, I, integer_to_list(I), I * 1000}, value = I * 1000})
     || I <- lists:seq(1,1000)].

search(Filters) ->
    Guards = [filter_to_guard(Filter) || Filter <- Filters],
    MatchHead = {row, {shell, '$1', '$2', '$3'}, '_'},
    Result = ['$_'],
    ets:select(?MODULE, [{MatchHead, Guards, Result}]).

filter_to_guard({time_higher_than, X}) -> {'<', X, '$1'};
filter_to_guard({time_lower_than, X}) -> {'>', X, '$1'};
filter_to_guard({name_is, X}) -> {'==', '$2', X};
filter_to_guard({id_is, X}) -> {'==', '$3', X}.
在中,您有关于匹配规格合成的更多信息

我建议使用

MatchHead = #row{key = {shell, '$1', '$2', '$3'}, value = '_'},
即使您需要调整记录定义以允许
'$x'
'
原子

<>也请考虑使用匹配表和/或使用连续表,如果使用大表。

编辑 通过滥用erlang术语和搜索记录中有用的默认值之间的完整顺序,您可以获得所需的:


-模块(匹配规格和防护装置)。
-导出([新建/0,填充/0,搜索/1])。
-记录(世界其他地区){
键::{shell,Time::integer(),Name::string(),ID::term()},
value::term()
}).
-记录(S1U)查询{
tsched_低=0,
tsched_高=未定义,
id='",
名称='''
}).
新建()->
ets:new(?MODULE,[set,named_table,{keypos,#row.key}])。
填充()->
[ets:insert(?MODULE,#row{key={shell,I,integer_to_list(I),I*1000},value=I*1000})
||我
MatchHead=#行{key={shell,$1',查询#s1shell_Query.name,查询#s1shell_Query.id},值='''''},

Guards=[{'>',High,'$1'},{'=您不能在状态定义记录中放入一个默认值(s1shell_查询,{tsched={{u ScLow,{u ScHigh},id=undf,type=undf})如果未从用户输入中发送,请签入。记录定义不允许我放入uuAtom,但我会再试一次。虽然您已经给了我一个我还没有想到的格式化方法!不幸的是,我刚刚推送了这部分代码,目前正在处理其他内容。我会尽快尝试。目前,我正在对照“undefined”检查用户搜索参数,然后生成不同的搜索函数,但正如我所说,它感觉很难看。我一直在使用它。示例记录定义-记录(状态,{message=[]::term(),tablename::binary()|“undefined”})。
MatchHead = #row{key = {shell, '$1', '$2', '$3'}, value = '_'},
Erlang/OTP 22 [erts-10.7.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1]

Eshell V10.7.1  (abort with ^G)
1>  c(match_spec_guards).
{ok,match_spec_guards}
2> match_spec_guards:new().
match_spec_guards
3> match_spec_guards:populate().
[true,true,true,true,true,true,true,true,true,true,true,
 true,true,true,true,true,true,true,true,true,true,true,true,
 true,true,true,true,true,true|...]
4>  rr(match_spec_guards).
[row,s1shell_query]
7> match_spec_guards:search(#s1shell_query{id = 14000}).
[#row{key = {shell,14,"14",14000},value = 14000}]
8> match_spec_guards:search(#s1shell_query{name = "14"}).
[#row{key = {shell,14,"14",14000},value = 14000}]
9> match_spec_guards:search(#s1shell_query{tsched_high = 20}).                 
[#row{key = {shell,1,"1",1000},value = 1000},
 #row{key = {shell,15,"15",15000},value = 15000},
 #row{key = {shell,6,"6",6000},value = 6000},
 #row{key = {shell,16,"16",16000},value = 16000},
 #row{key = {shell,8,"8",8000},value = 8000},
 #row{key = {shell,2,"2",2000},value = 2000},
 #row{key = {shell,9,"9",9000},value = 9000},
 #row{key = {shell,17,"17",17000},value = 17000},
 #row{key = {shell,12,"12",12000},value = 12000},
 #row{key = {shell,7,"7",7000},value = 7000},
 #row{key = {shell,13,"13",13000},value = 13000},
 #row{key = {shell,10,"10",10000},value = 10000},
 #row{key = {shell,3,"3",3000},value = 3000},
 #row{key = {shell,11,"11",11000},value = 11000},
 #row{key = {shell,19,"19",19000},value = 19000},
 #row{key = {shell,14,"14",14000},value = 14000},
 #row{key = {shell,5,"5",5000},value = 5000},
 #row{key = {shell,4,"4",4000},value = 4000},
 #row{key = {shell,18,"18",18000},value = 18000}]
10> match_spec_guards:search(#s1shell_query{tsched_low = 998}).
[#row{key = {shell,998,"998",998000},value = 998000},
 #row{key = {shell,999,"999",999000},value = 999000},
 #row{key = {shell,1000,"1000",1000000},value = 1000000}]