2013-04-04 24 views
4

朋友,Lucene.NET 2.9自定義過濾器添加授權

我是新來的Lucene ...
我成功地創建一個索引,添加的字段,我可以搜索等它的工作原理。

現在,我在我的數據庫中有一個視圖,告訴哪些用戶可以看到哪個文檔。這個視圖是使用幾個複雜的規則創建的,所以我想重用這個視圖。因此,我需要在Lucene搜索中添加一個過濾器,以刪除與查詢匹配但用戶無權訪問的文檔。
我現在要做的是:
- 將db文檔ID存儲在一個字段中。這是一個Guid,我把它作爲一個字符串存儲。
- 創建獲取所有文檔ID當前用戶可以訪問的自定義過濾器,然後篩選使用Lucene的領域

我有感覺,這會不會是有效的......用戶可以有上百訪問成千上萬的文件,所以我可能會檢索200 000個文件ID我需要過濾。 我想我必須緩存一些東西...
這是我寫的代碼,但它不起作用:當使用過濾器時它沒有返回文檔(它應該返回3個文檔)

public class LuceneAuthorisationFilter : Filter 
{ 
    public override DocIdSet GetDocIdSet(Lucene.Net.Index.IndexReader reader) 
    { 
     List<Guid> ids = this.load(); // Load list of ID from database 
     OpenBitSet result = new OpenBitSet(reader.MaxDoc); 

     int[] docs = new int[1]; 
     int[] freq = new int[1]; 

     for (int i = 0; i < ids.Count; i++) 
     { 
      Lucene.Net.Index.TermDocs termDocs = reader.TermDocs(new Lucene.Net.Index.Term("EmId", ids.ElementAt(i).ToString())); 

      int count = termDocs.Read(docs, freq); 
      if (count == 1) 
      { 
       result.FastSet(docs[0]); 
      } 
     } 
     return result; 
    } 
} 

你有什麼想法嗎?如何增加性能?

謝謝

編輯:
上述工程的代碼,問題只是該EMID場沒有索引。現在我已經改變,它的工作原理。
現在我想有任何提示,以提高性能


2ND編輯添加的反饋

注:測試環境包含25個000文件和文檔的列表訪問包含50個000號(因爲所有的文件都沒有

索引)

  • 使用自定義過濾器上面的:〜2600ms一日一次,2100ms接下來的時間作爲過濾緩存
  • 使用布爾查詢過濾器:〜4700ms話〜4000ms

這些表現欠佳..所以我再次搜索了一個找到的'FieldCacheTermsFilter'過濾器。

  • 使用FieldCacheTermsFilter:〜600毫秒的話〜60ms的

這是可接受的性能

PS:我還發現了另一個類似question

回答

3

談到演出始終是棘手的,當沒有號碼/測量結果。

這就是說,你在演出方面做了什麼?你有什麼瓶頸(IO/CPU /等),你有沒有將它與其他方法進行比較?

您是否確實需要提高性能?有關性能改進的討論不是關於「感覺」,而是圍繞基於證據和需要改進的嚴峻事實。

現在爲您的Filter,除非我沒有從問題中得到的東西,我不明白爲什麼你不能使用已經構建到Lucene中做什麼的努力。

這是我通常在Lucene中處理權限的東西,它總是適用於包含數十億文檔的索引。我通常使用具有最小年齡的LRU類型緩存來清除緩存中的項目。

IE:緩存100個項目,但如果最近最少使用的時間不超過15分鐘,則緩存更多。

如果您嘗試這樣的事情,那麼將它與您的方法進行比較並回來發佈一些性能數字可能會很有趣。

免責聲明:直接在這樣的textarea編寫的代碼,把它更像僞代碼比已經工作拷貝粘貼的解決方案:

// todo: probably some thread safety 
public class AccessFilterFactory 
{ 
    private static AccessFilterFactory _instance = new AccessFilterFactory();; 
    private AccessFilterFactory() 
    { 
    } 

    public AccessFilterFactory Instance 
    { 
     get 
     { 
      return _instance; 
     } 
    } 

    private Cache<int, Filter> someKindaCache = new Cache<int, Filter>(); 

    // gets a cached filter if already built, if not it creates one 
    // caches it and returns it 
    public Filter GetFilterForUser(int userId) 
    { 
     // return from cache if you got it 
     if(someKindaCache.Exists(userId)) 
      return someKindaCache.Get(userId); 

     // if not, build and cache it 
     BooleanQuery filterQuery = new BooleanQuery(); 
     foreach(string id in ids) 
     { 
      filterQuery.Add(new TermQuery(new Term("EmId", id)), BooleanClause.Occur.SHOULD); 
     } 
     Filter cachingFilter = new CachingWrapperFilter(new QueryWrapperFilter(filterQuery)); 
     someKindaCache.Put(userId, cachingFilter); 
     return cachingFilter; 
    } 

    // removes a new invalid filter from cache (permissions changed) 
    public void InvalidateFilter(int userId) 
    { 
     someKindaCache.Remove(userId); 
    } 
} 
+0

你說得對的演出「情」。我沒有發佈任何數字,因爲我還沒有。而且我也沒有「其他方法」來測試更好的性能。我期待着你發佈的內容:達到相同功能的不同方式,所以我可以嘗試選擇最好的。以及您收集的任何其他經驗。例如,使用200 000的BooleanQuery將會有效嗎?問題是,要回答這個問題,我需要編寫代碼和測試。如果有人已經知道這個答案,它可以爲我節省很多時間。謝謝你的發帖 – Fabske 2013-04-08 14:45:28

+0

我不知道,那需要測試。我目前可以獲得的數字是數千(2k-4k條款)。我的文檔被分組到安全類別中,這就是我過濾訪問的內容。 – 2013-04-09 19:26:00

+0

只是一些反饋:默認情況下,BooleanQuery接受最大1024個術語。這可以使用靜態屬性'BooleanQuery.MaxClauseCount'進行更改。但是使用25000個條件的布爾查詢比我在我的問題中寫的過濾器慢2倍。在「過濾器」上使用緩存可縮短搜索時間20% – Fabske 2013-04-17 09:52:47