倒置搜索:每个文档的短语

时间:2009-12-31 17:37:54

标签: mysql search indexing full-text-search lucene

我有一个包含短语(80-100个字符)的数据库,以及一些冗长的文档(50-100Kb),我想要一个给定文档的排序列表;而不是搜索引擎的通常输出,给定短语的文档列表。

我之前使用过MYSQL全文索引,并查看了lucene,但从未使用它。 它们似乎都适合比较短(搜索词)和长(文档)。

你怎么能得到这个的倒数?

4 个答案:

答案 0 :(得分:3)

我使用维基百科标题数据库做了类似的事情,并为每个~50KB的文档设法降低到几百毫秒。对于我的需求来说,这仍然不够快,但也许它可以为你工作。

基本上,这个想法是尽可能地使用哈希值,并且只对可能的匹配进行字符串比较,这种情况非常罕见。

首先,您获取数据库并将其转换为哈希数组。如果你有数十亿的短语,这可能不适合你。在计算哈希值时,请务必通过标记器传递短语,这将删除标点符号和空格。这部分只需要完成一次。

然后,你使用相同的标记器来查看文档,保留最后1,2,...,n个标记的运行列表,哈希。在每次迭代中,您都会对哈希数据库中的哈希值进行二进制搜索。

当您找到匹配项时,您会进行实际的字符串比较,看看是否找到了匹配项。

这里有一些代码,让你尝试一下我的意思,这个例子实际上并没有进行字符串比较:

            HashSet<Long> foundHashes = new HashSet<Long>();

            LinkedList<String> words = new LinkedList<String>();
            for(int i=0; i<params.maxPhrase; i++) words.addLast("");

            StandardTokenizer st = new StandardTokenizer(new StringReader(docText));
            Token t = new Token();
            while(st.next(t) != null) {
                String token = new String(t.termBuffer(), 0, t.termLength());
                words.addLast(token);
                words.removeFirst();

                for(int len=params.minPhrase; len<params.maxPhrase; len++) {
                    String term = Utils.join(new ArrayList<String>(words.subList(params.maxPhrase-len,params.maxPhrase)), " ");

                    long hash = Utils.longHash(term);

                    if(params.lexicon.isTermHash(hash)) {
                        foundHashes.add(hash);
                    }
                }
            }

            for(long hash : foundHashes) {
                if(count.containsKey(hash)) {
                    count.put(hash, count.get(hash) + 1);
                } else {
                    count.put(hash, 1);
                }
            }

答案 1 :(得分:0)

将每个短语转换为正则表达式并在文档上运行每个短语,计算出现次数是否会太慢?

如果这不起作用,也许你可以将所有短语组合成一个巨大的正则表达式(使用|),并编译它。然后,从文档中的每个字符开始运行那个巨大的正则表达式。通过字符计算匹配数。

答案 2 :(得分:0)

短语数据库有多大?我假设它非常大。

我会做以下事情:

  1. 通过其中一个词语对短语进行索引。您可以在每个短语中选择最不常见的单词。您可以通过假设该单词至少为例如更好地进行搜索。 5个字符长,如果它更短,则将字填充为5个字符。填充可以是单词之后的空格,后跟后续单词,以减少匹配,或者如果单词出现在短语的末尾,则为某些默认字符(例如“XX”)。

  2. 浏览您的文档,在必要时通过填充将每个单词(常见的单词可以丢弃)转换为密钥,然后检索短语。

  3. 通过这些关键字检索相关短语。

  4. 使用内存中文本搜索查找每个检索到的短语的出现次数。

  5. 我假设短语不能越过句子边界。在这种情况下,您可以将文档的每个句子读入数组中的子字符串,并使用子字符串函数在每个句子中搜索每个短语并计算出现次数,并为每个短语保留一个运行总和。

答案 3 :(得分:0)

也许阅读Peter Turney on keyphrase extraction会给你一些想法。总的来说,他的方法与其建议的方法有一些相似之处。