Last active
August 29, 2015 14:07
-
-
Save mocobeta/7bf66c343904520f0662 to your computer and use it in GitHub Desktop.
(Lucene) Spatial search のサンプル
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package indexer; | |
import java.io.File; | |
import java.io.IOException; | |
import java.util.HashMap; | |
import java.util.Map; | |
import org.apache.lucene.analysis.core.WhitespaceAnalyzer; | |
import org.apache.lucene.document.Document; | |
import org.apache.lucene.document.Field.Store; | |
import org.apache.lucene.document.IntField; | |
import org.apache.lucene.document.StoredField; | |
import org.apache.lucene.document.StringField; | |
import org.apache.lucene.index.IndexWriter; | |
import org.apache.lucene.index.IndexWriterConfig; | |
import org.apache.lucene.index.IndexableField; | |
import org.apache.lucene.spatial.SpatialStrategy; | |
import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy; | |
import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree; | |
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree; | |
import org.apache.lucene.store.Directory; | |
import org.apache.lucene.store.FSDirectory; | |
import org.apache.lucene.util.Version; | |
import com.spatial4j.core.context.SpatialContext; | |
import com.spatial4j.core.shape.Point; | |
public class SpatialIndexSample { | |
static Map<String, double[]> data = new HashMap<String, double[]>(); | |
static { | |
data.put("東京都写真美術館", new double[]{139.713549, 35.641653}); | |
data.put("国立西洋美術館", new double[]{139.776318, 35.715431}); | |
data.put("東京都現代美術館", new double[]{139.808303, 35.679762}); | |
data.put("東京国立近代美術館", new double[]{139.754704, 35.690631}); | |
data.put("東京都庭園美術館", new double[]{139.721043, 35.635801}); | |
data.put("東京都美術館", new double[]{139.773606, 35.717152}); | |
data.put("上野の森美術館", new double[]{139.775612, 35.712703}); | |
data.put("芸術大学美術館", new double[]{139.773540, 35.719622}); | |
data.put("板橋区立美術館", new double[]{139.644651, 35.784251}); | |
data.put("練馬区立美術館", new double[]{139.636560, 35.737093}); | |
data.put("世田谷美術館", new double[]{139.622305, 35.631598}); | |
data.put("山種美術館", new double[]{139.714445, 35.653333}); | |
data.put("戸栗美術館", new double[]{139.693766, 35.661412}); | |
data.put("bunkamura", new double[]{139.696291, 35.661136}); | |
data.put("ワタリウム美術館", new double[]{139.713683, 35.670585}); | |
data.put("太田記念美術館", new double[]{139.705276, 35.669407}); | |
data.put("森美術館", new double[]{139.729526, 35.660448}); | |
data.put("国立新美術館", new double[]{139.726750, 35.665225}); | |
data.put("根津美術館", new double[]{139.718088, 35.662264}); | |
data.put("サントリー美術館", new double[]{139.730589, 35.666177}); | |
data.put("竹久夢二美術館", new double[]{139.763913, 35.714908}); | |
data.put("弥生美術館", new double[]{139.763884, 35.714958}); | |
data.put("礫川浮世絵美術館", new double[]{139.752347, 35.708757}); | |
data.put("ブリヂストン美術館 ", new double[]{139.772651, 35.678805}); | |
data.put("相田みつを美術館", new double[]{139.764297, 35.676995}); | |
data.put("出光美術館", new double[]{139.762252, 35.676740}); | |
data.put("東京ステーションギャラリー", new double[]{139.768371, 35.681757}); | |
data.put("ニューオータニ美術館", new double[]{139.735518, 35.681039}); | |
data.put("羽田空港ディスカバリーミュージアム", new double[]{139.788095, 35.552128}); | |
data.put("龍子記念館", new double[]{139.716176, 35.582408}); | |
} | |
private static String idxdir = "geoindex"; | |
private SpatialContext ctx; | |
private SpatialStrategy strategy; | |
private int maxLevels = 11; // Geohash の精度 | |
private Directory directory; | |
public static void main(String[] args) throws IOException { | |
SpatialIndexSample indexer = new SpatialIndexSample(); | |
IndexWriter writer = indexer.getWriter(); | |
indexer.doIndexPoints(writer); | |
writer.close(); | |
} | |
public SpatialIndexSample() throws IOException { | |
// SpatialStrategy の初期化 | |
// 緯度経度は Geohash を使ってエンコード | |
this.ctx = SpatialContext.GEO; | |
SpatialPrefixTree grid = new GeohashPrefixTree(ctx, maxLevels); | |
this.strategy = new RecursivePrefixTreeStrategy(grid, "geofield"); | |
this.directory = FSDirectory.open(new File(idxdir)); | |
} | |
private void doIndexPoints(IndexWriter writer) throws IOException { | |
int id = 1; | |
for (Map.Entry<String, double[]> entry : data.entrySet()) { | |
Document doc = new Document(); | |
doc.add(new IntField("id", id, Store.YES)); | |
doc.add(new StringField("name", entry.getKey(), Store.YES)); | |
// Point オブジェクトからIndexableFieldを作る | |
// makePoint() は引数にX座標(経度)、Y座標(緯度)をとる | |
Point pt = ctx.makePoint(entry.getValue()[0], entry.getValue()[1]); | |
for (IndexableField field : strategy.createIndexableFields(pt)) { | |
// フィールド追加 | |
doc.add(field); | |
} | |
// (option) 経度、緯度は表示のためストアしておく | |
doc.add(new StoredField(strategy.getFieldName(), pt.getX() + "," + pt.getY())); | |
writer.addDocument(doc); | |
id++; | |
} | |
} | |
private IndexWriter getWriter() throws IOException { | |
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_0, | |
new WhitespaceAnalyzer()); | |
return new IndexWriter(this.directory, config); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package spacial; | |
import java.io.File; | |
import org.apache.lucene.document.Document; | |
import org.apache.lucene.index.DirectoryReader; | |
import org.apache.lucene.index.IndexReader; | |
import org.apache.lucene.queries.function.ValueSource; | |
import org.apache.lucene.search.IndexSearcher; | |
import org.apache.lucene.search.MatchAllDocsQuery; | |
import org.apache.lucene.search.Sort; | |
import org.apache.lucene.search.TopDocs; | |
import org.apache.lucene.spatial.SpatialStrategy; | |
import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy; | |
import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree; | |
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree; | |
import org.apache.lucene.store.Directory; | |
import org.apache.lucene.store.FSDirectory; | |
import com.spatial4j.core.context.SpatialContext; | |
import com.spatial4j.core.distance.DistanceUtils; | |
import com.spatial4j.core.shape.Point; | |
public class SpatialSearchSample { | |
private static String idxdir = "geoindex"; | |
private static SpatialContext ctx = SpatialContext.GEO; | |
private static int maxLevels = 11; | |
public static void main(String[] args) { | |
try { | |
Directory dir = FSDirectory.open(new File(idxdir)); | |
IndexReader r = DirectoryReader.open(dir); | |
IndexSearcher searcher = new IndexSearcher(r); | |
SpatialPrefixTree grid = new GeohashPrefixTree(ctx, maxLevels); | |
SpatialStrategy strategy = new RecursivePrefixTreeStrategy(grid, "geofield"); | |
// 品川駅(139.740419, 35.630418)から近い順に5件を検索 | |
Point pt = ctx.makePoint(139.740419, 35.630418); | |
ValueSource source = strategy.makeDistanceValueSource(pt, DistanceUtils.DEG_TO_KM); | |
Sort sort = new Sort(source.getSortField(false).rewrite(searcher)); | |
TopDocs hits = searcher.search(new MatchAllDocsQuery(), 5, sort); | |
for (int i = 0; i < hits.scoreDocs.length; i++) { | |
int docid = hits.scoreDocs[i].doc; | |
Document doc = searcher.doc(docid); | |
System.out.println(doc.get("name") + " (" + doc.get(strategy.getFieldName()) + ")"); | |
} | |
dir.close(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package spacial; | |
import java.io.File; | |
import org.apache.lucene.document.Document; | |
import org.apache.lucene.index.DirectoryReader; | |
import org.apache.lucene.index.IndexReader; | |
import org.apache.lucene.search.Filter; | |
import org.apache.lucene.search.IndexSearcher; | |
import org.apache.lucene.search.MatchAllDocsQuery; | |
import org.apache.lucene.search.TopDocs; | |
import org.apache.lucene.spatial.SpatialStrategy; | |
import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy; | |
import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree; | |
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree; | |
import org.apache.lucene.spatial.query.SpatialArgs; | |
import org.apache.lucene.spatial.query.SpatialOperation; | |
import org.apache.lucene.store.Directory; | |
import org.apache.lucene.store.FSDirectory; | |
import com.spatial4j.core.context.SpatialContext; | |
import com.spatial4j.core.distance.DistanceUtils; | |
public class SpatialSearchSample2 { | |
private static String idxdir = "geoindex"; | |
private static SpatialContext ctx = SpatialContext.GEO; | |
private static int maxLevels = 11; | |
public static void main(String[] args) { | |
try { | |
Directory dir = FSDirectory.open(new File(idxdir)); | |
IndexReader r = DirectoryReader.open(dir); | |
IndexSearcher searcher = new IndexSearcher(r); | |
SpatialPrefixTree grid = new GeohashPrefixTree(ctx, maxLevels); | |
SpatialStrategy strategy = new RecursivePrefixTreeStrategy(grid, "geofield"); | |
// 品川駅(139.740419, 35.630418)から半径5km圏内でフィルタする | |
SpatialArgs sargs = new SpatialArgs(SpatialOperation.Intersects, | |
ctx.makeCircle(139.740419, 35.630418, | |
DistanceUtils.dist2Degrees(5, DistanceUtils.EARTH_MEAN_RADIUS_KM))); | |
Filter filter = strategy.makeFilter(sargs); | |
TopDocs hits = searcher.search(new MatchAllDocsQuery(), filter, 100); | |
// 座標 (139.5, 35.5) を左上, 座標 (139.7, 35.8) を右下とする長方形の範囲でフィルタする | |
/* | |
SpatialArgs sargs = new SpatialArgs(SpatialOperation.Intersects, | |
ctx.makeRectangle(139.5, 139.7, 35.5, 35.8)); | |
Filter filter = strategy.makeFilter(sargs); | |
TopDocs hits = searcher.search(new MatchAllDocsQuery(), filter, 100); | |
*/ | |
for (int i = 0; i < hits.scoreDocs.length; i++) { | |
int docid = hits.scoreDocs[i].doc; | |
Document doc = searcher.doc(docid); | |
System.out.println(doc.get("name") + " (" + doc.get(strategy.getFieldName()) + ")"); | |
} | |
dir.close(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment