我正在构建一个电子邮件过滤器,我需要一种方法来有效地将单个电子邮件与大量过滤器/规则匹配。电子邮件可以在以下任何字段中匹配:
目前有超过5000个过滤器(并且还在增长),它们都在我们的PostgreSQL(9.1)数据库的单个表中定义。每个过滤器可能包含一个或多个上面填充了Python正则表达式的字段。
目前正在进行过滤的方法是选择所有过滤器并将其加载到内存中。然后,我们针对每封电子邮件迭代它们,直到在所有非空白字段上找到肯定匹配。不幸的是,这意味着任何一封电子邮件都可能有多达30,000(5000 x 6)次重新匹配操作。显然,这不会随着更多过滤器的添加而扩展(实际上它已经没有)。
有更好的方法吗?
到目前为止我考虑的选项:
将保存的python正则表达式转换为POSIX样式表达式,以利用PostgreSQL的SIMILAR TO表达式。这真的会更快吗?在我看来,它只是将负载转移到其他地方。
基于每个用户定义过滤器。虽然这不太实际,因为我们的系统用户实际上可以从大量预定义过滤器中受益。
切换到基于文档的搜索引擎,如弹性搜索,其中第一封要过滤的电子邮件将保存为规范表示。通过查找类似的电子邮件,我们可以缩小到要测试的特定功能集并获得正面匹配。
切换到贝叶斯过滤器,它还可以为我们提供一些机器学习功能,以检测类似的电子邮件或对现有电子邮件的更改,这些电子邮件仍然可以匹配的概率足以猜测它们是相同的。这听起来很酷,但我不确定它的扩展性也会特别好。
还有其他选择或方法需要考虑吗?
答案 0 :(得分:3)
PostgreSQL版本9.1中的trigram支持可能会为您提供所需的内容。
http://www.postgresql.org/docs/9.1/interactive/pgtrgm.html
几乎可以肯定,它将成为9.2(计划于2012年夏季发布)的可行解决方案,因为新版本知道如何使用trigram索引快速匹配正则表达式。在我们的商店,我们发现三元组指数的速度非常好。
另外,如果您想要进行“最近邻居”搜索,根据与搜索参数的相似性找到K个最佳匹配,则三元组索引非常棒 - 它实际上会从索引扫描中按顺序返回行“距离”。搜索KNN-GiST进行撰写。
答案 1 :(得分:0)
这些正则表达式有多复杂?如果它们确实是正则表达式(没有所有疯狂的python扩展),那么你可以将它们全部组合成一个正则表达式(作为备选方案),然后使用一个简单的(即内存中)正则表达式匹配器。
我不确定这会起作用,但我怀疑你会惊喜地发现正则表达式编译成一个小得多的状态机,因为它会合并常见状态。
另外,对于快速正则表达式引擎,请考虑使用快速扫描的nrgrep。从一个标题跳到另一个标题时,这应该会给你加速(我自己没有使用它,但它们是朋友的朋友,当我阅读它时,纸张看起来非常整洁)。