LuceneでMoreLikeThisがうまくいかない(いった)

C:\Lucene\files\にTwitterのユーザー名.txtがあり、TwitetrのPOSTが1行に1つ
C:\Lucene\indexにindexを作成済み

1つのユーザー名.txtから類似したユーザー名.txtを探す

import java.io.File;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import org.apache.jackrabbit.core.query.lucene.MoreLikeThis;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.ja.JapaneseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
class SearchJFilesFromDoc {
	public static void main(String[] args) throws CorruptIndexException, IOException, ParseException {
		System.setProperty("sen.home", "D:\\Software\\java\\sen");
		String index = "C:\\Lucene\\index";
		Directory dir = new RAMDirectory(new File(index));
		IndexReader reader = IndexReader.open(dir);
		IndexSearcher searcher = new IndexSearcher(dir);
		MoreLikeThis mlt = new MoreLikeThis(reader);
		Analyzer analyzer = new JapaneseAnalyzer();
		mlt.setAnalyzer(analyzer);
		String user = "snkken";
		String userTweet = "C:\\Lucene\\files\\" + user + ".txt";
		Reader target = new StringReader(userTweet);
		Query query = mlt.like(target);
		System.out.println("Searching for: " + query.toString("contents"));
		TopDocs docs = searcher.search(query, 10);
		for (ScoreDoc scoreDoc : docs.scoreDocs) {
			int docId = scoreDoc.doc;
			Document doc = searcher.doc(docId);
			System.out.println("path" + doc.get("path"));
		}
		searcher.close();
	}
}


実行結果

log4j:WARN No appenders could be found for logger (net.java.sen.Dictionary).
log4j:WARN Please initialize the log4j system properly.
Searching for: 

研究室の仲間の協力を得て無事動作!

		Query query = mlt.like(new BufferedReader(new InputStreamReader(new FileInputStream(userTweet), "SJIS")));
//		Reader target = new StringReader(userTweet);
//		FileInputStream fis = new FileInputStream(target);
//		Query query = mlt.like(target);
log4j:WARN No appenders could be found for logger (net.java.sen.Dictionary).
log4j:WARN Please initialize the log4j system properly.
Searching for: あめ kt スクレ の ロイド 帽子 じょ クーラ 赤い w だ 人 カ ええ は 数 ー に た トランスフォーマ て 明日 さん も ない
pathC:\Lucene\files\snkken.txt
その他結果

Solr

最終的にはWebから検索するためにSolr使う予定だけど、文章の特徴語検索には使えるのかな

仕組みをまったく理解してないから明日試しにSolrを動かしてみよう
といいながら今日動かしてみた

うまくいかないー
あとで最初から1つ1つまとめながらやってみよう

Luceneで文章の類似文章検索

Luceneは普通に使うと単語からの検索なので文章との比較はできない。
が、実は文章のためのメソッドが用意されていた
MoreLikeThis

サンプルの修正が終わったので上記の修正開始
少し苦戦中
けどこれが完成すれば基本的な機能は完成でwebに実装するだけだ!
駄目だ・・・
多分Queryの生成がうまくいってない

import org.apache.jackrabbit.core.query.lucene.MoreLikeThis;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.ja.JapaneseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;

class SearchJFilesFromDoc {
	public static void main(String[] args) throws CorruptIndexException, IOException, ParseException {
		System.setProperty("sen.home", "D:\\Software\\java\\sen");
		String index = "C:\\Lucene\\index";
		IndexReader reader = IndexReader.open(index);
		IndexSearcher searcher = new IndexSearcher(index);
		MoreLikeThis mlt = new MoreLikeThis(reader);
		Analyzer analyzer = new JapaneseAnalyzer();
		mlt.setAnalyzer(analyzer);
		mlt.setFieldNames(new String[] { "contetns", "path" });
		String user = "snkken";
		String userTweet = "C:\\Lucene\\files\\" + user + ".txt";
		Reader target = new StringReader(userTweet);
		Query query = mlt.like(target);

		System.out.println("Searching for: " + query.toString("contents"));
		TopDocs docs = searcher.search(query, 10);
		for (ScoreDoc scoreDoc : docs.scoreDocs) {
			int docId = scoreDoc.doc;
			Document doc = searcher.doc(docId);
			System.out.println("path" + doc.get("path"));
		}
		searcher.close();
	}
}


別のお話
単語を抽出する際の品詞を指定できるみたい。
類似ユーザー検索だと、名詞に限定したほうがいいよね。
wikipediaはてなの固有名詞だけに限定するのもありかも

これはシステムが動いてからおいおい試していこう

SearchJFiles.javaの修正

下記を参考に開始


恐らく一番の肝はHitsクラスを使わないでTopDocsクラスを使うところ
とりあえずjavadocを読む

修正完了
30行くらい短くなってWarnningが消えた

こんな感じ
細かいところは改造してます
出力してるdo.get("path")とか

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.ja.JapaneseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Searcher;
import org.apache.lucene.search.TopDocs;

class SearchJFiles {
	public static void main(String[] args) throws CorruptIndexException, IOException, ParseException {
		String index = "C:\\Lucene\\index";
		System.setProperty("sen.home", "D:\\Software\\java\\sen");
		Searcher searcher = new IndexSearcher(index);
		Analyzer analyzer = new JapaneseAnalyzer();

		BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
		while (true) {
			System.out.print("Query: ");
			String line = in.readLine();
			if (line.length() == -1)
				break;
			QueryParser parser = new QueryParser("contents", analyzer);
			Query query = parser.parse(line);
			System.out.println("Searching for: " + query.toString("contents"));
			TopDocs docs = searcher.search(query, 10);
			for (ScoreDoc scoreDoc : docs.scoreDocs) {
				int docId = scoreDoc.doc;
				Document doc = searcher.doc(docId);
				System.out.println(doc.get("path"));
			}
			searcher.close();
		}
	}
}