我正在写一个信息检索程序,PHP+MYSQL,数据库是这么设计的(为简化省去和问题无关的列):
词表T: id, term;其中term列表示关键词,做了唯一索引;
数据样例:[1,'云计算'],[2,'大数据']
文档表D:id, length;其中length列表示文档长度,用于计算排名以便排序搜索结果;
数据样例:[1,300],[2,500]
关系表C:tid,did,count; 表示哪个词出现在哪个文档多少次?前两列是外键,count列也用于计算排名;
数据样例:[1,1,3],[1,2,5],[2,2,10]
对文档集编制索引,也就是向这三个表插入数据,这一步已经完成。
接下来处理查询,用户输入的是自然语言,例如“今年云计算和大数据发展趋势”。
我用PHP提取出关键词“云计算”“大数据”,现在是两个,然后调用存储过程来快速检索:
CALL SP2('云计算','大数据');
存储过程会返回文档id数组,并根据相关度排序,相关度的计算比较复杂,会用到D.length和C.count,以及一些统计数据,比如文档总共有多少个?其中包含词'云计算'的文档有多少个?……
我的问题是,目前我写了SP(K),SP2(K1,K2);可PHP提取出来的关键词数量可以任意多,总不能为每种数量编写一个存储过程吧?请问如何编写一个存储过程,能高效的处理任意多个关键词呢?
我先简要展示一下SP2的伪代码(可能有语法错误,您凑付看,明白意思就好):
-- 计算文档总数,包含关键词K1、K2的文档数
select count(*) into TotalD from D;
select count(*) into TotalDK1 from D
join C on C.did = D.id
join T on C.tid = T.id
where T.term = K1;
select count(*) into TotalDK2 from D
join C on C.did = D.id
join T on C.tid = T.id
where T.term = K2;
-- 检索文档,根据相关度排名,返回给PHP
select D.id, 计算相关度(TotalD, TotalDK1, TotalDK2, length, count) AS rel
from
(
select D.id, D.length, C.count from D join ... where T.term = K1
union all
select D.id, D.length, C.count from D join ... where T.term = K2
)
group by D.id
order by rel desc;
大致如此,您明白了吧,如果再写SP3、SP4、……要了命了!
谢谢!
为啥用数据库实现,用全文搜索啊,一般都有权重功能的...