2009-12-31 62 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. 我假設短語不能跨越句子邊界。在這種情況下,可以將文檔的每個句子讀入數組中的子字符串,並使用子字符串函數來搜索每個短語的每個句子並計算出現次數,併爲每個短語保留一個運行總和。