2013-02-08 13 views
2

我想在我的項目中使用Lucene搜索,因爲它的速度很快,但是存在問題。如何在lucene搜索之前通過外鍵過濾我的數據?

我有數據庫表用戶和友誼。我想通過搜索表單找到用戶的朋友。使用lucene,我只能通過搜索查詢找到所有用戶,獲取他們的id,將它們放到實體框架中,然後只帶用戶的朋友,但如果系統中的用戶數千萬,並且該用戶的朋友只有幾個?所以我需要接受用戶的朋友,然後通過搜索查詢進行篩選。我怎樣才能做到這一點?我聽說過Linq的Lucene,但我不確定這是我需要的。請幫我解決我的麻煩。

P.S.對不起,我的英語,我來自烏克蘭,不會說英語很好:)

我找到了解決辦法。我將在索引中存儲好友ID並通過這些ID查找用戶朋友。這不是最好的解決方案,因爲索引經常會被編輯,但我無法實現另一個想法。

+0

如果一個用戶只有幾個朋友而不是你爲什麼要爲用戶編制索引?如果我是你,我會首先嚐試使用某種在線搜索(例如,獲取朋友列表並對它們進行迭代)。你有沒有嘗試過這樣的事情? – Hari

+0

嗯...好吧,可能你是對的。但如果用戶有10K的朋友呢? –

+0

比你的問題立場,你可以開始祈禱有人會給你一個有用的答案。 – Hari

回答

0

這可以通過使用filters來完成。這是一個簡短的演示,將結果限制爲僅包含FriendsWith:Beta的文檔。這需要重新編制 受更改的友誼連接影響的文檔。可以在contrib包中找到TermsFilter類。

using System; 
using System.Collections.Generic; 
using Lucene.Net.Analysis; 
using Lucene.Net.Documents; 
using Lucene.Net.Index; 
using Lucene.Net.Search; 
using Lucene.Net.Store; 
using Directory = Lucene.Net.Store.Directory; 
using Version = Lucene.Net.Util.Version; 

namespace ConsoleApplication { 
    public static class Program { 
     public static void Main(string[] args) { 
      var directory = new RAMDirectory(); 
      var analyzer = new KeywordAnalyzer(); 

      using (var writer = new IndexWriter(directory, analyzer, IndexWriter.MaxFieldLength.UNLIMITED)) { 
       var users = new [] { "Alfa", "Beta", "Gamma", "Delta" }; 
       var friendships = new Dictionary<String, String[]> { 
        { "Alfa", new [] { "Beta", "Gamma", "Delta" } }, 
        { "Beta", new [] { "Gamma", "Delta" } }, 
        { "Gamma", new [] { "Delta" } }, 
        { "Delta", new String[0] } // Noone likes Delta. 
       }; 

       foreach (var userName in users) { 
        var doc = new Document(); 
        doc.Add(new Field("Name", userName, Field.Store.YES, Field.Index.NO)); 

        foreach (var friendName in friendships[userName]) { 
         doc.Add(new Field("FriendsWith", friendName, Field.Store.NO, Field.Index.NOT_ANALYZED_NO_NORMS)); 
        } 

        writer.AddDocument(doc); 
       } 

       writer.Commit(); 
      } 

      // This should be the real query provided by the user (city, age, description, ...) 
      var query = new MatchAllDocsQuery(); 

      // Create a filter limiting the result to those being friends with the current user, 
      // in this example the user "Beta". 
      var filter = new TermsFilter(); 
      filter.AddTerm(new Term("FriendsWith", "Gamma")); 

      var reader = IndexReader.Open (directory, readOnly: true); 
      var searcher = new IndexSearcher(reader); 

      var result = searcher.Search (query, filter, 10); 
      foreach(var topDoc in result.ScoreDocs) { 
       var doc = searcher.Doc(topDoc.Doc); 
       var foundName = doc.Get ("Name"); 
       Console.WriteLine("Matched user '{0}'", foundName); 
      } 

      Console.ReadLine(); 
     } 
    } 
}