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を動かしてみよう
といいながら今日動かしてみた
- メモ solrインストール
- 日本語形態素解析器Senを導入する その2 lucene-jaのインストール - Solr, Python, MacBook Air schema定義
うまくいかないー
あとで最初から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(); } } }