.net

37 라인의 코드로 자신의 인터넷과 웹사이트를 Full-Text 검색하기

duraboys 2007. 5. 3. 10:59

 

DotLucene: 뛰어난 full-text 검색 엔진


37 라인으로 Full-Text 검색 코드를 작성할 수 있을까? 글쎄, 나는 약간의 편법을 쓸 예정이고, 이를 위해 DotLucene를 이용할 것이다. DotLucene은 Jakarta Lucene 검색 엔진을 George Aroush et al이 .NET으로 포팅 한 것이다. 기능은 대략 이러하다.

  • Win Form이나 console application 등 ASP.NET에서 사용 가능하다.
  • 매우 좋은 성능을 낸다.
  • 검색 결과에 순위가 매겨져 있다.
  • 결과에 검색 쿼리가 강조 된다.
  • 구조적이거나 비구조적인 데이터를 검색한다.
  • 메타베이스 검색
  • 색인의 크기는 색인된 텍스트의 대략 30%이다.
  • 또한 완전하게 색인된 문서들을 저장할 수 있다.
  • 244 KB 짜리 단일 어셈블리에서 Pure managed .NET
  • 매우 친숙한 라이센스(Apache Software License 2.0).
  • 지역화가 가능하다(브라질어, 체코어, 중국어, 네덜란드어, 영어, 프랑스어, 일본어, 한국어 그리고 러시아어를 포함).
  • 확장 가능하다(소스코드가 포함되어 있다).

경고


라인 수를 너무 심각하게 따지지 말라. 여기에서는 핵심 기능을 37 라인의 코드를 넘기지 않고 구현하는 것을 보여줄 것이다. 하지만, 실제 애플리케이션에서는 더 많은 시간을 들여야 할 수도 있다.

 

데모 프로젝트


어떻게 동작하는 지 보여줄 간단한 데모 프로젝트를 빌드 할 것이다.

  • 색인 HTML 파일들은 특정 디텍토리 안에서 찾는다(하위 디렉토리 포함).
  • ASP.NET 애플리케이션을 통한 색인 검색
  • 검색 결과의 쿼리 단어를 강조

DotLucene은 더 많은 잠재적인 가능성을 가지고 있다. 실제 애플리케이션에서는 이러한 기능들을 원할 것이다.

  • 디렉토리에 새로운 문서가 나타나면 이를 색인에 추가한다. 따라서 전체 색인을 재빌드 할 필요가 없다.
  • 다른 파일 타입을 포함한다. DotLucene은 평문(plain text)으로 변환할 수 있는 어떠한 파일 타입이라도 색인 할 수 있다.

왜 Microsoft Indexing Server를 이용하지 않는가?


만약 Indexing Server에 만족한다면, 별 문제없다. 하지만, DotLucene은 더 많은 강점들을 가지고 있다.

  • DotLucene은 100% managed code의 단일 어셈블리이다. 이는 외부에 의존할 필요가 없음을 말한다.
  • shared hosting를 이용하기 때문에, 미리 색인을 준비하였다면 퍼미션을 줄 필요가 없다.
  • 데이터베이스나 웹 등의 소스에서라도 어떠한 타입의 데이터라도 색인하여 사용할 수 있다. 때문에 평문을 indexer로 제공해야 할 필요가 있다. 소스의 로딩과 파싱은 당신의 선택에 달려 있다.
  • 색인에 포함된 특정한 속성("fields")을 줄 수 있다. 이들 필드를 통해 검색할 수 있다.
  • 오픈 소스이다.
  • 쉽게 확장 가능하다.

1 라인: 색인 생성


다음의 코드는 새로운 색인을 생성하여 디스크에 저장한다. directory는 색인이 저장될 디렉토리 경로이다.

 

IndexWriter writer =

   new IndexWriter(directory, new StandardAnalyzer(), true);


이번 예제에서는, scratch로부터 색인을 생성한다. 이는 필수가 아니며, 존재하는 색인을 열거나 문서를 추가할 수 있다. 게다가 존재하는 문서를 삭제하거나 새로운 버전을 추가하여 업데이트 할 수 있다.

 

2 – 12 라인: 문서 추가


각 HTML 문서에서 색인에 두 필드를 추가한다.

  • text 필드는 HTML 파일 (with stripped tags)의 텍스트를 포함한다. 텍스트는 스스로 색인에 저장되지 않는다.
  • path 필드는 파일 경로를 포함한다. 여기에 지정된 색인에 전체가 색인되고 저장된다.

public void AddHtmlDocument(string path)

{

    Document doc = new Document();

 

    string rawText;

    using (StreamReader sr =

       new StreamReader(path, System.Text.Encoding.Default))

    {

        rawText = parseHtml(sr.ReadToEnd());

    }

   

    doc.Add(Field.UnStored("text", rawText));

    doc.Add(Field.Keyword("path", path));

    writer.AddDocument(doc);

}


13 – 14 라인: 색인의 최적화와 저장


문서를 추가한 후에 indexer를 닫아야 한다. 최적화는 검색 성능을 향상시킨다.

 

writer.Optimize();

writer.Close();


15 라인: 검색을 위한 색인 열기


어떠한 검색이라도 실행하기 전에 색인을 열어야 한다. directory 는 색인이 저장된 디렉토리 경로이다.

 

IndexSearcher searcher = new IndexSearcher(directory);


16 – 27 라인: 검색

 

이제 쿼리를 파싱 할 수 있다 (text는 검색을 위한 기본 필드이다).

 

Query query =

   QueryParser.Parse(q, "text", new StandardAnalyzer());

Hits hits = searcher.Search(query);


변수 hits는 결과 문서들의 집합이다. 검색은 이를 통해 이루어 지고, 결과는 DataTable에 저장된다.

 

DataTable dt = new DataTable();

dt.Columns.Add("path", typeof(string));

dt.Columns.Add("sample", typeof(string));

 

for (int i = 0; i < hits.Length(); i++)

{

    // get the document from index

    Document doc = hits.Doc(i);

 

    // get the document filename

    // we can''t get the text from the index

    //because we didn''t store it there

    DataRow row = dt.NewRow();

    row["path"] = doc.Get("path");

 

    dt.Rows.Add(row);

}


Lines 28 - 37: 쿼리 강조

 

highlighter를 생성하자. 강조에는 굵게(<B>phrase</B>)를 사용한다..

 

QueryHighlightExtractor highlighter =

  new QueryHighlightExtractor(query, new StandardAnalyzer(),

                         "<B>", "</B>");


결과를 fetch하는 동안, 오리지널 텍스트의 적절한 부분을 로드한다.

 

for (int i = 0; i < hits.Length(); i++)

{

    // ...

    string plainText;

    using (StreamReader sr =

      new StreamReader(doc.Get("filename"),

                  System.Text.Encoding.Default))

    {

        plainText = parseHtml(sr.ReadToEnd());

    }

    row["sample"] =

       highlighter.GetBestFragments(plainText, 80, 2, "...");

    // ...

}


리소스들

 

 

출처 : http://www.codeproject.com/aspnet/DotLuceneSearch.asp