Lucene.Net 使用 Snowball (詞幹還原)

摘要:Lucene.Net 使用 Snowball

Lucene.Net 有一個 Contrib Library  ,  Snowball  

 

若要取得 Library 可到 下列網址下載
https://www.nuget.org/packages/Lucene.Net.Contrib/3.0.3

 

它提供詞幹還原的功能 , 就像 organization 會被還原成 organ 

 

Sample : 

 

我們將插入一索引名為 text , 值為 walking , 無論我們搜尋 walk , walked

或者 walking , 其搜尋結果都是我們插入的索引值 , walking

 

Step 1 : Build Index 

 


 private void BuildIndex()
    {
        DirectoryInfo dirInfo = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory.ToString() + "\\App_Data");
        FSDirectory dir = FSDirectory.Open(dirInfo);
        IndexWriter iw = new IndexWriter(dir, new SnowballAnalyzer(Version.LUCENE_30, "English"), true, IndexWriter.MaxFieldLength.UNLIMITED);
        Document doc = new Document();
        Field field = new Field("text", "walking", Field.Store.YES, Field.Index.ANALYZED, Field.TermVector.NO);
        doc.Add(field);
        iw.AddDocument(doc);
        iw.Optimize();
        iw.Commit();
        iw.Close();
    }

 

 

Step 2 : Search 

 


public void Search(string KeyWord)
    {
        DirectoryInfo dirInfo = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory.ToString() + "\\App_Data");
        FSDirectory dir = FSDirectory.Open(dirInfo);

        IndexSearcher search = new IndexSearcher(dir, true);

        QueryParser parser = new QueryParser(Version.LUCENE_30, "text", new SnowballAnalyzer(Version.LUCENE_30, "English"));

        Query query = parser.Parse(KeyWord);

        var hits = search.Search(query, null, search.MaxDoc).ScoreDocs;

        foreach (var res in hits)
        {
            Response.Write(string.Format("text:{0}"
                                        , search.Doc(res.Doc).Get("text").ToString() + "
"));
        }
    }

 

 

Result : 


text:walking

 

當我們使用 SnowBall Analyzer 建立 Index 時 , 它會將我們輸入的單字 walking 詞幹還原成 walk , 

 

然後將它存進 Index , 如下圖 , 我們使用 Luke.Net 來觀察 Index 

 

 

這時候我們在 Search 時 , 也需要使用 Snowball Analyzer ,  如果我們搜尋字串 walking , 

 

它也會將它還原成 walk , 這樣子就直接產生我們在上述的結果了

 

另外關於 Snowball 的建構式中 , 第二個參數 name ,  其 Api 解釋為  

Builds the named analyzer with no stop words  

 

若是你輸入了 english 或者空字串 , 他都會產生錯誤 ,

 

其原因是 , 你必須輸入他所支援的國家名稱 , 因為他會透過 name 參數呼叫相對應的 語言詞幹還原 class

 

也就是當你輸入 English , 他就會去呼叫 EnglishStemmer

 

我們可以透過 ILSpy 來觀察 

 

Step 1 : 

 

Snowball  繼承了 Lucene.Net.Analysis.Analyzer Class  , 而在這裡他 override 了 base 的 TokenStream , 

 

我們可以看到它回傳了 SnowballFilter instance 

 


public override TokenStream TokenStream(string fieldName, TextReader reader)
		{
			TokenStream result = new StandardTokenizer(this.matchVersion, reader);
			result = new StandardFilter(result);
			result = new LowerCaseFilter(result);
			if (this.stopSet != null)
			{
				result = new StopFilter(StopFilter.GetEnablePositionIncrementsVersionDefault(this.matchVersion), result, this.stopSet);
			}
			return new SnowballFilter(result, this.name);
		}

 

 

Step 2 : 

 

我們可以看到它會在這裡藉由取得 name 參數組成 class 名稱 , 然後藉由反射去取得 class instance 

 


public SnowballFilter(TokenStream input, string name) : base(input)
		{
			try
			{
				Type stemClass = Type.GetType("SF.Snowball.Ext." + name + "Stemmer");
				this.stemmer = (SnowballProgram)Activator.CreateInstance(stemClass);
			}
			catch (Exception e)
			{
				throw new SystemException(e.ToString());
			}
			this.termAtt = this.AddAttribute();
		}

 

Step 3 : 接下來我們來看看有那些語言的詞幹還原可以使用

 

 

還滿多的 smiley