2009-12-31 63 views
3

我有一个充满短语(80-100个字符)和一些长文档(50-100Kb)的数据库,并且我想要给出一个给定文档的短语排列列表;而不是搜索引擎的通常输出,也就是给定短语的文档列表。反向搜索:每个文档的短语

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

你会如何得到这个相反的?

回答

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); 
       } 
      } 
+0

几百毫秒是可以接受的。我会给这个方法一个去 – Tourch 2009-12-31 19:21:57

0

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

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

+0

我可以交易时间建立索引,以便查找短语列表(针对给定的文档)尽可能快。 – Tourch 2009-12-31 17:47:47

0

短语数据库有多大?我认为它非常大。通过在其中的一个关键词

  1. 指数短语:

    我会做以下。您可以在每个短语中选择最不常用的单词。您可以通过假设该单词至少是例如长度为5个字符,如果长度较短,则将该单词填充为5个字符。填充可以是单词后面的空格,接着是后面的单词,以减少匹配,或者如果单词出现在短语结尾处,则可以使用某个默认字符(例如“XX”)。

  2. 通过您的文档,通过填充(如有必要)将每个单词(常见的单词可以丢弃)转换为一个键,检索短语。

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

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

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