说我想要识别文档的几页(可能大约500页以上)中出现的所有单词。我已经完成了查找单词出现在哪个页面的工作。因此,例如,我想列出计算机一词出现的所有页面。
将这些数据存储为可通过Web服务快速搜索的最佳方法是什么?我的直觉就是做一些事情:
表格结构: varchar(30)WORD,blob PAGES
让PAGES字段为出现该单词的所有页面的逗号分隔列表,然后将其展开并在查询与WORD字段匹配时列出所有页面。我想知道是否有更有效的方法来实现这一目标?我可能会使用MySQL和PHP / Zend,因为这是我最熟悉的。但如果你有更好的想法,我肯定愿意听到它们。
该表可能会变得非常长,因为我需要为文档中的每个唯一单词添加一行。也许我会设置一个不超过3或4个字符的限制,但我仍然可以想象超过10-20k字。如果我按字母顺序排列行列表,我可以以某种方式在我的数据库服务器上更容易吗? (即苹果,苹果,分支是按升序排列的吗?)MySQL可以处理这个吗?还有别的东西可以更好地处理吗?
最后,是否有更好的结构模式,以后可能会让我收集/提供有趣的数据? (即,向用户提供经常出现在附近的相关单词等)。
答案 0 :(得分:4)
您必须规范化您的数据库。
首先是一个存储页面的表
table pages (
id unsigned integer auto_increment primary key,
page blob,
other_interesting_data_about_a_page )
然后是一个用于保存单词的表
table wc (
id unsigned integer auto_increment primary key
word varchar(20) unique key,
count unsigned integer default 1,
other_interesting_data_about_a_word.... )
然后是一个表格,用于将单词链接到页面
table word_page (
word_id unsigned integer,
page_id unsiged integer,
pos_in_page unsigned integer, /*position*/
primary key pk (word_id, page_id, pos_in_page) )
现在您可以查询页面中的单词数量:
SELECT COUNT(*)
FROM word_page
WHERE page_id = 123
或在页面中重复单词'the'的次数。
SELECT COUNT(*)
FROM word_page wp
INNER JOIN wc ON (wp.word_id = wc.id)
WHERE wp.page_id = 123 AND wc.word = 'the'
警告语
让PAGES字段成为所有页面的逗号分隔列表.....
永远不要在数据库中使用CSV,这是你可以使用的最糟糕的反模式,如果你堕落,它会一遍又一遍地咬你。
如果您感觉到需要,请将自己踢到头部,直到冲动消失为止,然后再使用一个或两个单独的桌子。
答案 1 :(得分:3)
与标准化相反,这对于这个特定问题通常是一种良好的做法,但是空间效率很低,你可能想要坚持你的结构,但用一个位向量替换你的blob中的页面列表(仍然在blob列),每个位代表一个页面。优点是,对于500页,即使该单词出现在所有页面中(500/8 = 62.5),一个单词的该向量的最大大小也将是63字节。
在位域内,每个页面对应一个位号:如果位号N为ON,则表示该单词出现在第N页,否则它不出现在第N页。 这是DBIx SQL text indexing implementation基本使用的结构 位从右到左编号,可以删除非重要的0。
例如,如果第3,4和12页中出现“计算机”一词,则该值为:
二进制100000001100
(十进制表示= 2060)。
如果仅在第400页出现,则数字1
后跟399 0's
。如果它出现在每个页面上,则该值将是数字1
的500倍。
我一直在postgresql数据库中使用该表示(加分区)来全文索引邮件内容,并且我发现它的扩展性非常好,这与仅对非常小的表现良好的天真规范化实现相反数据集。
答案 2 :(得分:1)
为了便于维护和索引,我将设置一个带有计算的primarey键的映射表: id BIGINT AUTO_INCREMENT, 字VARCHAR(30), 页面INT, ... 并为单词和页面构建索引。 这样,您就更灵活,不需要爆炸列表甚至可以访问某些统计信息(哪些页面使用更多独特的单词等)。
MySQL(以及所有其他关系数据库引擎)使用树结构构建自己的内部索引,无需预先对数据进行排序。
这个表很容易被MySQL处理。可能还有更快的其他数据库引擎,但这是一个不错的开始。
当然你可以添加更多的表,即word,other_word,distance,这一切都取决于你的规范以及解析器的可能性。
如果你有时间浏览一下,看看searchengines如何,例如solr / lucene正在处理这些事情