有关将MySQL数据转换为Prolog规则以进行探索性挖掘的具体规则吗?

时间:2013-06-13 13:44:18

标签: mysql prolog swi-prolog data-conversion

我有三个表(现在),一个有2000行,另外两个有大约160万行。它们具有相互关联的列,但它们不是正式的FK字段。我编写了一个C ++程序来生成基于源MySQL数据的规则文件,如下所示:

if T{ C1, C2...Cn } is the table definition
then the rule would be:
    T(C1, C2, Cn).

我的转换实用程序将整数展开,其他任何内容都放在单引号内,因此INT(n),DECIMAL等成为Prolog数字,其他所有内容都是原子。

我的问题是:如果我想为包含26个字段的表/规则编写搜索规则,是否有“元级别”表达方式:

findStuffById(I,FieldIWant1,FieldIwant2etc) :-
    tablename(_,_,I,_,FieldIWant1,_,_,_FieldIWant2etc,_,_,....).

还是我必须创建“更简单”的规则,然后必须使用“_”或变量来捕捉我想要的东西?

编写像...这样的规则的前景。

findThisById(X)     :- tablename(X,_,_,_,_,This,_,_).
findThatById(X)     :- tablename(X,_,_,That,_,_,_,_).
findTheOtherById(X) :- tablename(X,_,_,_,_,_,_,TheOther).

... ad adause ...令人不安!

到目前为止,我唯一的想法是,我可能需要在规则中创建复合术语以将事物分组在一起,即减少规则中的变量数量,但这可能会限制未来查询的“自由”?我不是Prolog专家;我已经玩了好几个小时了,并渴望在我自己的日常工作中找到真实世界的用途。

我想我的转换程序也可以编码生成苦差规则,以便我不必手动编码。大表每个有26和28列,所以你可以看到它的发展方向!

欢迎任何关于如何进行的建议;我不像我想的那样使用Prolog,而且我总是想学习更多!

我想创建一个SWI-Prolog Web服务器,该服务器将使用相同的原始数据与ElasticSearch服务器正面交锋,以查看哪些是响应ad-hoc查询的快速响应。除非你预先创建一个嵌入了索引的复合文档,否则ES似乎不会做传统连接,这也可能有利于使用Prolog。

感谢。 肖恩。

2 个答案:

答案 0 :(得分:2)

您可以使用nth1/1和“univ”运算符,执行以下操作:

fieldnames(t, [id,this,that]).
get_field(Field, Tuple, Value) :- 
    Tuple =.. [Table|Fields],
    fieldnames(Table, Names),
    nth1(Idx, Names, Field),
    nth1(Idx, Fields, Value).

您需要为每个表结构创建fieldnames/2条记录,并且必须将表结构传递给此查询。它不会非常有效,但它会起作用。

?- get_field(this, t(testId, testThis, testThat), Value)
Value = testThis

然后,您可以轻松地在此基础上构建访问者:

findThisById(X, This) :- get_field(this, X, This).

修改:Boris正确地指出arg/3将以更少的工作完成此任务:

get_field(Field, Tuple, Value) :-
    functor(Tuple, Table, _),
    fieldnames(Table, Names),
    nth1(Idx, Names, Field),
    arg(Idx, Tuple, Value).

Prolog太棒了。

答案 1 :(得分:1)

在实际的电子商务数据库中,我使用了像

这样的代码
update_price(File, Pid, Cn, Manu) :-
    product(Pid, [tax_class_id = Tid, /*cost = Cost,*/ price = CurrPrice]),
    tax_rate(_, [tax_class_id = Tid, rate = R]),
    manufacturer(Manu, name = NameM),
    (   ( NameM == 'Gruppo Aboca' ; NameM == 'L\'Amande' )
        ->  % Pr is Cost * 3 / 2
        togli_iva(R, Cn, Pr)
    ;   togli_iva(R, Cn, NoIva),
        Pr is NoIva * 2
    ),
    Delta is abs(CurrPrice - Pr),
    (   Delta > 0.01
    ->  Prx is round(Pr * 100) / 100,
        format(File, 'update product set price=~w where product_id=~d~@', [Prx, Pid, eol])
    ;   true
    ).

product,tax_rate,manufacturer是具有已知结构的实际表名。例如,产品有26列,tax_rate有8,....

我有声明

:- dynamic 
    ...
    product/2,product/26,
    ...
    tax_rate/2,tax_rate/8,
    ...

从SQL转储中读取数据,当在内存中声明时,我构建了product / 2访问器,负责从名称到位置的字段转换。

我不建议使用这种方法,因为对你的数据来说太慢了。相反,您可以使用goal_expansion/2并在编译时将任何对表的调用(field1 = Value1,field2 = Value2)转换为对应的表调用(,Value1,_,Value2) ) - Prolog的位置方式。

这应该会从SWI-Prolog索引中挤出最佳性能,最近更新后可用于所有列。

当然,要获得更多细节,您应该发布元数据格式......

编辑:如果您对简单的单字段访问者感兴趣(正如我从评论中理解为Daniel的答案),您可以尝试使用库(record)。