2014-09-29 64 views
1

我几天前开始使用Lucene,但在调试我的解决方案时,我在Lucene中发现了一个麻烦。为了尝试解决这个问题,我创建新的自定义项目,并开始测试不同的解决方案,但后2天,我的Lucene搜索投降的解决方案...Lucene .NET更新数据

我的问题:

我创建一个定制类,创建标准阵列这类的。 创建Document对象并通过IndexWriter对其进行索引。它的一切正常。搜索工作很好。但是当我尝试通过使用IndexWriter.UpdateDocument来更新任何文档并且使用例如索引'5'来说它更新文档时,其创建具有id = 5的新文档。最后,我有2个id = 5的文档,并且旧,和新的。如果在IndexWriter的构造函数'true'中替换id,那么当我更新它的同一个代码时,它只保存1个更新后的文档,并且删除之前的所有索引。确切地说,我无法全部更新所有的基础,因为我的基础很大(我的构造函数大约有600个互联网资源),我只需要更新更改后的数据(将其替换为新数据),并保存索引。可能有人知道我做错了什么?

P.S.对不起我的英语不好。

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

你可以尝试减少你的程序到最低限度,以便其他人更容易帮助调试,阅读代码等? – 2014-09-29 07:27:56

+0

我不知道我可以减少那里,但我可以扩大。 首先我创建自定义类obkects(mydoc)的数组。 通过将每个mydoc转换为Document(Lucene对象)并将其索引为IndexWriter,将它添加到索引后。接下来,我在Lucene索引中显示所有存在的文档。 我使用IndexWriter updater.UpdateDocument进行更改之后。要查看在Lucene索引中做了哪些更改,请再次在索引中显示所有存储的文档。在文档中通过单词“test”进行搜索并显示结果文档ID后,字段“内容”中的单词为“测试”。它的全部。 – velgames 2014-09-29 09:05:37

+0

我没有IndexWriter的知识,但是我可以在代码中看到一些可能成为问题的东西。 (1)在您的更新程序中,您只有10个文档而不是11个。文档[10]不在列表中。 (2)同样,你似乎创建新文档而不是调用旧文档并更新它们。我可能错了。 – SollyM 2014-09-29 09:52:07

回答

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”的文本。