類似検索やりたくて試したんだけどなんかうまくいかねーです。 Lucene詳しいかた、教えてくだしあ><
2009/10/07: 解決したので後ろに追記しました。
package hoge;
import java.io.*;
import net.moraleboost.lucene.analysis.ja.StandardMeCabAnalyzer;
import org.apache.lucene.*;
public class MeCabTest {
public static final String DIC_ENCODING = System.getProperty("net.moraleboost.mecab.encoding");
private static StandardMeCabAnalyzer analyzer = null;
private static FSDirectory directory = null;
private IndexWriter writer = null;
private static final String DIR = "/path/to/index";
public void setUp() throws Exception {
writer = new IndexWriter(directory, analyzer, new MaxFieldLength(4096));
Document doc = new Document();
addField(doc, "text", "ほげほげ");
....
....
writer.commit();
writer.optimize();
writer.close();
}
private void addField(Document doc, String name, String value) throws Exception {
Field field = new Field(name, value, Store.YES, Field.Index.ANALYZED, Field.TermVector.YES);
doc.add(field);
writer.addDocument(doc);
}
public static void main(String[] args) {
MeCabTest t = new MeCabTest();
IndexSearcher searcher = null;
IndexReader reader = null;
analyzer = new StandardMeCabAnalyzer(DIC_ENCODING, "");
directory = FSDirectory.open(new File(DIR));
t.setUp();
reader = IndexReader.open(DIR, false);
searcher = new IndexSearcher(directory, true);
QueryParser parser = new QueryParser("text", analyzer);
parser.setDefaultOperator(QueryParser.Operator.OR);
MoreLikeThis mlt = new MoreLikeThis(reader);
mlt.setAnalyzer(analyzer);
mlt.setMinTermFreq(1);
mlt.setFieldNames(new String[]{"text"});
Query query = mlt.like(new ByteArrayInputStream("ほげ".getBytes()));
TopDocs topDocs = searcher.search(query, 100);
if (topDocs.totalHits > 0) {
for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
Document doc = searcher.doc(scoreDoc.doc);
System.out.println(doc.get("text"));
}
}
}
}
try〜catchとか省略。addField(…);のところ、実際にはニュースサイトから本文引っ張ってきて、いくつかいれた。7個くらい適当に選んで、3個くらいは同じニュース(台風18号関連)を違うサイトから引用した。
MoreLikeThis#like()には、台風18号関連のさらに別のニュースを入れてみたが、topDocs.totalHitsがindexに入れたニュース数と同数、つまり全部ヒットになっちゃった。しかも1件目に入れたやつしか表示されない…なんのこっちゃい??
明日以降もうちょっと調べて、わかったら追記しよう…
[追記] すげーポカやってるし…。単純にDocumentクラスを使い回しちゃダメってことみたい。そりゃそうだよね、別のDocumentとして扱いたいんだから、インスタンスも別だわな。というわけでaddFieldメソッドにDocument渡すのやめて、メソッド内でDocumentクラスのインスタンスを作るようにしたら、上手く動くようになりました。