2014-09-29 4 views
1

몇 일 전에 Lucene을 사용하기 시작했지만 디버그에서 내 솔루션은 Lucene에서 한 가지 문제를 발견했습니다.Lucene .NET 업데이트 데이터

내가 생성 한 사용자 정의 클래스, 표준 배열을 만듭니다하려고 들어 것은 내가 새로운 사용자 정의 프로젝트를 만들고 시작 테스트 다른 솔루션을하지만, 내가 항복 루씬과 솔루션을 검색 2 일 ...

내 문제 후이 문제를 해결 이 클래스의 Document 개체를 만들고 IndexWriter로 인덱싱합니다. 그것들 모두 잘 작동합니다. 검색 작업은 훌륭합니다. 그러나 IndexWriter.UpdateDocument를 사용하여 문서를 업데이트하려고 할 때 인덱스가 '5'인 문서를 업데이트 할 때 id = 5 인 새 문서를 만듭니다. 마지막으로 id = 5 인 문서가 2 개 있고 오래된 문서입니다. , 그리고 새로운. IndexWriter의 생성자에서 'true'를 사용하여 ID를 바꾼 경우 동일한 코드를 업데이트하면 업데이트 된 문서가 하나만 저장되고 전에 인덱싱 된 모든 내용이 제거됩니다. 정확히 말하면, 기지가 크고 (생성자의 인터넷 자원이 600 정도이기 때문에) 모든 기지를 업데이트 할 수는 없으며, 변경된 데이타 만 (새로운 것으로 대체해야 함) 이전에 색인을 생성해야합니다. 어떤 사람이 내가 뭘 잘못하고 있는지 알아?

P. 내 영어로 미안해.

class mydoc 
{ 
    public string id; 
    public string name; 
    public string content; 

    public mydoc(string ID, string Name, string Content) 
    { 
     id = ID; 
     name = Name; 
     this.content = Content; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine("Create data array..."); 
     mydoc[] docs = new mydoc[11]; 
     docs[0] = new mydoc("0", "Name0", "tet 5"); 
     docs[1] = new mydoc("1", "Name1", "aaaa text"); 
     docs[2] = new mydoc("2", "Name2", "and me test "); 
     docs[3] = new mydoc("3", "Name3", "I am new tes 3"); 
     docs[4] = new mydoc("4", "Name4", "I am new tes 4"); 
     docs[5] = new mydoc("5", "Name5", "I am new test 5"); 
     docs[6] = new mydoc("6", "Name6", "I am new text 6"); 
     docs[7] = new mydoc("7", "Name7", "I am new text 7"); 
     docs[8] = new mydoc("8", "Name8", "I am new text 8"); 
     docs[9] = new mydoc("9", "Name9", "I am new text 9"); 
     docs[10] = new mydoc("10", "Name10", "I am new test 10"); 

     Console.WriteLine("index processing..."); 
     var dir = new DirectoryInfo("tmp"); 
     FSDirectory fsdir = FSDirectory.Open(dir); 
     Analyzer analyzer = new StandardAnalyzer(Net.Util.Version.LUCENE_29); 
     IndexWriter writer = new IndexWriter(fsdir , analyzer,true, IndexWriter.MaxFieldLength.UNLIMITED); 

     for (int i = 0; i < docs.Length; i++) 
     { 
      writer.AddDocument(Convert(docs[i])); 
     } 
     writer.Optimize(true); 

     writer.Close(true); 

     Console.WriteLine("index done !"); 

     IndexReader reader = IndexReader.Open(fsdir, true); 
     for (int i = 0; i < reader.MaxDoc;i++) 
     { 
      Document doc = reader.Document(i); 
      Console.WriteLine("id = \"{0}\", Name = \"{1}\", Context = \"{2}\"", doc.Get("ID"),doc.Get("Name"),doc.Get("Content")); 
     } 
     reader.Close(); 

     // Update custom base 
     IndexWriter updater = new IndexWriter(fsdir, analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED); 
     updater.UpdateDocument(new Term("0"), Convert(new mydoc("0", "New name 0", "prosto obitr test")), new StandardAnalyzer(Net.Util.Version.LUCENE_30)); 
     updater.UpdateDocument(new Term("1"), Convert(new mydoc("1", "New name 1", "prosto obitr test")),new StandardAnalyzer(Net.Util.Version.LUCENE_30)); 
     updater.UpdateDocument(new Term("2"), Convert(new mydoc("2", "New name 2", "prosto obitr test")), new StandardAnalyzer(Net.Util.Version.LUCENE_30)); 
     updater.UpdateDocument(new Term("3"), Convert(new mydoc("3", "New name 3", "prosto obitr test")), new StandardAnalyzer(Net.Util.Version.LUCENE_30)); 
     updater.UpdateDocument(new Term("4"), Convert(new mydoc("4", "New name 4", "prosto obitr test")), new StandardAnalyzer(Net.Util.Version.LUCENE_30)); 
     updater.UpdateDocument(new Term("5"), Convert(new mydoc("5", "New name 5", "prosto obitr test")), new StandardAnalyzer(Net.Util.Version.LUCENE_30)); 
     updater.UpdateDocument(new Term("6"), Convert(new mydoc("6", "New name 6", "prosto obitr test")), new StandardAnalyzer(Net.Util.Version.LUCENE_30)); 
     updater.UpdateDocument(new Term("7"), Convert(new mydoc("7", "New name 7", "prosto obitr test")), new StandardAnalyzer(Net.Util.Version.LUCENE_30)); 
     updater.UpdateDocument(new Term("8"), Convert(new mydoc("8", "New name 8", "prosto obitr test")), new StandardAnalyzer(Net.Util.Version.LUCENE_30)); 
     updater.UpdateDocument(new Term("9"), Convert(new mydoc("9", "New name 9", "prosto obitr test")), new StandardAnalyzer(Net.Util.Version.LUCENE_30)); 

     updater.Optimize(); 
     updater.Close(true); 

     reader = IndexReader.Open(fsdir, true); 
     Console.WriteLine("New updated data:"); 
     for (int i = 0; i < reader.MaxDoc; i++) 
     { 
      Document doc = reader.Document(i); 
      Console.WriteLine("id = \"{0}\", Name = \"{1}\", Context = \"{2}\"", doc.Get("ID"), doc.Get("Name"), doc.Get("Content")); 
     } 

     Console.ReadKey(); 


     Console.WriteLine("search processing..."); 
     string query = "test"; 
     fsdir = FSDirectory.Open(dir); 
     IndexSearcher searcher = new IndexSearcher(fsdir, true); 
     Console.WriteLine("Searching phrase \"{0}\"", query); 
     List<KeyValuePair<int, int>> results = find(query, searcher); 

     searcher.Close(); 
     fsdir.Close(); 

     Console.WriteLine("Results:"); 
     for (int i = 0; i < results.Count; i++) 
     { 
      try 
      { 
       // Display founded id 
       Console.WriteLine(results[i].Value); 
      } 
      catch (Exception ex) 
      { 
       continue; 
      } 
     } 
     Console.WriteLine("\n\rDone !"); 
     Console.ReadKey(); 

    } 

    static List<KeyValuePair<int,int>> find(string query, IndexSearcher searcher) 
    { 
     var parser = new MultiFieldQueryParser(Net.Util.Version.LUCENE_30, new[] { "Name", "Content" }, new SimpleAnalyzer()); 
     var score = searcher.Search(parser.Parse(query), 99).ScoreDocs; 
     var docIDs = score.Select(x => new KeyValuePair<int, int> 
      (
       x.Doc, int.Parse(searcher.Doc(x.Doc).Get("ID")) 
      ) 
      ).ToList(); 
     return docIDs; 
    } 


    static Document Convert(mydoc doc) 
    { 
     var document = new Document(); 
     document.Add(new Field("ID", doc.id, Field.Store.YES, Field.Index.NOT_ANALYZED)); 
     document.Add(new Field("Name", doc.name, Field.Store.YES, Field.Index.ANALYZED)); 
     document.Add(new Field("Content", doc.content, Field.Store.YES, Field.Index.ANALYZED)); 

     return document; 
    } 
} 

이 경우 doc [10]은 색인에서 제외됩니다.

IndexWriter updater = new IndexWriter(fsdir, analyzer, true, IndexWriter.MaxFieldLength.UNLIMITED); 

의 경우 '사실' '거짓'으로 대체, 대신 기존 대체 새 문서를 만들 수 있습니다.

updater.commit()도 도움이되지 않았습니다.

+0

다른 사람들이 디버깅, 코드 읽기 등을보다 쉽게 ​​할 수 있도록 프로그램을 최소한으로 줄일 수 있습니까? –

+0

나는 내가 무엇을 줄일 수 있는지 알지 못하지만, 나는 expalain 할 수있다. 먼저 사용자 정의 클래스 객체 (mydoc)로 배열을 만듭니다. 각 mydoc을 Document (Lucene 객체)로 변환하고 IndexWriter로 색인화하여 색인에 추가 한 후 다음으로 Lucene 색인에 존재하는 모든 문서를 표시합니다. IndexWriter updater.UpdateDocument를 사용하여 변경 한 후. Lucene 인덱스에서 수행 된 변경 내용을 보려면 다시 인덱스에 저장된 모든 문서를 표시하십시오. 그리고 문서에서 단어 "test"로 검색 한 후 결과 문서 ID를 표시하면 필드 "Content"에 단어 "test"가 표시됩니다. 그 모두. – velgames

+0

IndexWriter에 대한 지식이 없지만 문제가 될 수있는 몇 가지 사항을 코드에서 볼 수 있습니다. (1) 귀하의 업데이터에서 당신은 단지 10 문서가 아닌 11. Doc [10]가 목록에 없습니다. (2) 또한 이전 문서를 호출하고 업데이트하는 대신 새 문서를 만드는 것처럼 보입니다. 내가 틀렸을지도 모른다. – SollyM

답변

1

문제가 해결되었습니다. 그것의가 (내 경우) 같은 기간의 새 인스턴스를 만들 필요가

IndexUpdater.UpdateDocument(Term term, Document doc); 

: 내 잘못 입력 기간이 아닌 올바른 이해했다

updater.UpdateDocument(new Term("ID", "5"), Convert(new mydoc("5", "New name 5", "simple new test text")), new StandardAnalyzer(Net.Util.Version.LUCENE_30)); 

어디 기간 생성자 필드 "ID"에서 색인 플래그가없는 고유 필드이고 "5"는 색인의 이전 문서에서 이전 값 필드 "ID"의 텍스트입니다.