1

私はapacheluceneを使用してログクエリシステムを開発しようとしています。2つのファイルにインデックスを付けてから、クエリ文字列を検索するデモコードを開発しました。

最初のファイルにはデータmacleanが含まれています

2番目のファイルにはデータピントが含まれています

ベローは私がインデックス作成に使用したコードです

 fis = new FileInputStream(file);
  DataInputStream in = new DataInputStream(fis);
  BufferedReader br = new BufferedReader(new InputStreamReader(in));
  String strLine;
  Document doc = new Document();

  Document doc = new Document();
    doc.add(new TextField("contents", new BufferedReader(new InputStreamReader(fis, "UTF-8"))));

    doc.add(new StoredField("filename", file.getCanonicalPath()));

    if (indexWriter.getConfig().getOpenMode() == OpenMode.CREATE) {

       System.out.println("adding " + file);
      indexWriter.addDocument(doc);
   } else {

        System.out.println("updating " + file);
        indexWriter.updateDocument(new Term("path", file.getPath()), doc);
      }  

このコードを使用すると、プロファーの結果が得られます。ただし、ファイル名のみを保存しているため、ディスプレイにはファイル名のみを表示できます。

だから私はコードを変更し、このコードを使用してファイルの内容も保存しました

        FileInputStream fis = null;
        if (file.isHidden() || file.isDirectory() || !file.canRead() || !file.exists()) {
            return;
        }
        if (suffix!=null && !file.getName().endsWith(suffix)) {
            return;
        }
        System.out.println("Indexing file " + file.getCanonicalPath());

        try {
          fis = new FileInputStream(file);
        } catch (FileNotFoundException fnfe) {
          System.out.println("File Not Found"+fnfe);

       }
      DataInputStream in = new DataInputStream(fis);
      BufferedReader br = new BufferedReader(new InputStreamReader(in));
      String strLine;   
      String Data="";
     while ((strLine = br.readLine()) != null) 
         {
            Data=Data+strLine;
         }

        Document doc = new Document();
        doc.add(new TextField("contents", Data, Field.Store.YES));
        doc.add(new StoredField("filename", file.getCanonicalPath()));

        if (indexWriter.getConfig().getOpenMode() == OpenMode.CREATE) {

           System.out.println("adding " + file);
          indexWriter.addDocument(doc);
       } else {

            System.out.println("updating " + file);
            indexWriter.updateDocument(new Term("path", file.getPath()), doc);
          }

私の理解によると、結果の数は1になるはずです。また、macleanを含むファイルのファイル名と内容が表示されるはずです。

しかし、代わりに私は結果を次のように取得します

- - - - - - - - - - - -結果 - - - - - - - - - - - - -

一致するドキュメントの総数が0件見つかりました0

コードで何か問題がありますか、それとも論理的な説明がありますか?最初のコードが機能し、2番目のコードが機能しないのはなぜですか?

検索クエリコード

 try
   {
    Directory directory = FSDirectory.open(indexDir);
    IndexReader reader = DirectoryReader.open(directory);
    IndexSearcher searcher = new IndexSearcher(reader);
    Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_41);

    QueryParser parser = new QueryParser(Version.LUCENE_41, "contents", analyzer);
    Query query = parser.parse(queryStr);
    System.out.println("Searching for: " + query.toString("contents"));
    TopDocs results = searcher.search(query, maxHits);

    ScoreDoc[] hits = results.scoreDocs;
    int numTotalHits = results.totalHits;

    System.out.println("\n\n\n-----------------------Results--------------------------\n\n\n");
   System.out.println(numTotalHits + " total matching documents");


    for (int i = 0; i < numTotalHits; i++) {
        int docId = hits[i].doc;
        Document d = searcher.doc(docId);

                   System.out.println(i+":File name is: "+d.get("filename"));
                   System.out.println(i+":File content is: "+d.get("contents"));



    }
    System.out.println("Found " + numTotalHits);
   }
   catch(Exception e)
   {
    System.out.println("Exception Was caused in SimpleSearcher");
    e.printStackTrace();

   }
4

4 に答える 4

1

正確な問題は、インデックス付きフィールドのBufferedReaderを作成するまでに、ファイル全体が既に読み取られており、ストリームがファイルの最後にあり、それ以上読み取ることができないことだと思います。あなたはへの呼び出しでそれを修正することができるはずですfis.reset();

ただし、そうすべきではありません。同じデータを2つの別々のフィールドに保存しないでください。1つはインデックス作成用で、もう1つは保存用です。代わりに、データの保存とインデックス作成の両方に同じフィールドを設定します。 TextFieldには、次のようなインデックスだけでなくデータも保存できるctorがあります。

doc.add(new TextField("contents", Data, Field.Store.YES));
于 2013-03-11T16:04:35.220 に答える
1

TextFieldの代わりにStoredFieldを使用する

doc.add(new StoredField( "Data"、Line));

テキストフィールドを使用すると、文字列がトークン化され、その結果、同じものを検索できなくなります。Stored Fieldは、トークン化せずに文字列全体を格納します。

于 2013-03-19T08:48:02.160 に答える
0

コードに2つの問題があると思います。

まず、あなたはほぼリアルタイムの検索を使用しておらず、読む前にライターをコミットしていなかったことに気づきました。LuceneのIndexReaderは、インデックスのスナップショットを取得します。NRTが使用されていない場合はコミットされたバージョン、NRTが使用されている場合はコミットされたバージョンとコミットされていないバージョンの両方です。これが、IndexReaderが変更を認識できない理由である可能性があります。読み取りと書き込みを同時に行う必要があるようですので、NRT検索を使用することをお勧めします(IndexReader reader = DirectoryReader.open(indexWriter);

2番目の問題は、@ femtoRgonが言ったように、保存したデータが期待したものではない可能性があることです。ファイルのコンテンツを保存用に追加すると、EOL文字が失われるように見えることに気付きました。Lukeを使用してインデックスを確認することをお勧めしますhttp://www.getopt.org/luke/

于 2013-03-13T03:31:55.453 に答える
0

これはLucene4.5で機能します。doc.add(new TextField( "Data"、Data、Field.Store.YES));

于 2013-10-16T20:35:03.387 に答える