lucene spatial 6.1搜索附近的饭店
生活随笔
收集整理的這篇文章主要介紹了
lucene spatial 6.1搜索附近的饭店
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1.maven用依賴如下
<properties>
<lib.lucene.version>6.1.0</lib.lucene.version>
</properties>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>${lib.lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>${lib.lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-spatial</artifactId>
<version>${lib.lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-spatial-extras</artifactId>
<version>${lib.lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-smartcn</artifactId>
<version>${lib.lucene.version}</version>
</dependency>
2.直接上代碼
package org.xpen.hello.search.lucene;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.NumericDocValuesField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TermQuery;
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.RAMDirectory;
import org.junit.Test;
import org.locationtech.spatial4j.context.SpatialContext;
import org.locationtech.spatial4j.distance.DistanceUtils;
import org.locationtech.spatial4j.shape.Point;
import org.locationtech.spatial4j.shape.Shape;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Lucene spatial演示
* 出處:官方j(luò)unit代碼
*/
public class SpatialExample {
@Test
public void test() throws Exception {
init();
indexPoints();
search();
}
/** Spatial4j上下文 */
private SpatialContext ctx;// "ctx" is the conventional variable name
/** 提供索引和查詢模型的策略接口 */
private SpatialStrategy strategy;
/** 索引目錄 */
private Directory directory;
protected void init() {
// SpatialContext也可以通過SpatialContextFactory工廠類來構(gòu)建
this.ctx = SpatialContext.GEO;
//網(wǎng)格最大11層, geohash的精度
int maxLevels = 11;
//Spatial Tiers
SpatialPrefixTree grid = new GeohashPrefixTree(ctx, maxLevels);
this.strategy = new RecursivePrefixTreeStrategy(grid, "myGeoField");
this.directory = new RAMDirectory();
}
private void indexPoints() throws Exception {
IndexWriterConfig iwConfig = new IndexWriterConfig(new SmartChineseAnalyzer());
IndexWriter indexWriter = new IndexWriter(directory, iwConfig);
JsonFactory jsonFactory = new JsonFactory();
jsonFactory.enable(JsonParser.Feature.ALLOW_COMMENTS);
ObjectMapper mapper = new ObjectMapper(jsonFactory);
BufferedReader br = new BufferedReader(new InputStreamReader(
SpatialExample.class.getClassLoader().getResourceAsStream("search/lucene/shop.json")));
String line = null;
while ((line = br.readLine()) != null) {
ShopBean shopBean = mapper.readValue(line, ShopBean.class);
//這里的x,y即經(jīng)緯度,x為Longitude(經(jīng)度),y為Latitude(緯度)
Document document = newSampleDocument(shopBean.getId(), shopBean.getName(), ctx.makePoint(shopBean.getLongitude(), shopBean.getLatitude()));
indexWriter.addDocument(document);
}
indexWriter.close();
}
private Document newSampleDocument(int id, String title, Shape... shapes) {
Document doc = new Document();
doc.add(new StoredField("id", id));
doc.add(new NumericDocValuesField("id", id));
doc.add(new TextField("name", title, Store.YES));
// Potentially more than one shape in this field is supported by some
// strategies; see the javadocs of the SpatialStrategy impl to see.
for (Shape shape : shapes) {
for (Field f : strategy.createIndexableFields(shape)) {
doc.add(f);
}
// store it too; the format is up to you
// (assume point in this example)
Point pt = (Point) shape;
doc.add(new StoredField(strategy.getFieldName(), pt.getX() + " " + pt.getY()));
}
return doc;
}
private void search() throws Exception {
searchInner("密室");
System.out.println("----------------");
searchInner("咖啡");
}
private void searchInner(String keyword) throws Exception {
IndexReader indexReader = DirectoryReader.open(directory);
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
// --Filter by circle (<= distance from a point)
// Search with circle
// note: SpatialArgs can be parsed from a string
Point pt = ctx.makePoint(121.41791, 31.21867);
// the distance in km
ValueSource valueSource = strategy.makeDistanceValueSource(pt, DistanceUtils.DEG_TO_KM);
//按距離由近及遠(yuǎn)排序
Sort distSort = new Sort(valueSource.getSortField(false)).rewrite(indexSearcher); // false=asc dist
SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects,
ctx.makeCircle(pt, DistanceUtils.dist2Degrees(3.0, DistanceUtils.EARTH_MEAN_RADIUS_KM)));
Query query = strategy.makeQuery(args);
BooleanQuery.Builder bqb = new BooleanQuery.Builder();
bqb.add(query, BooleanClause.Occur.MUST);
bqb.add(new TermQuery(new Term("name", keyword)), BooleanClause.Occur.MUST);
TopDocs docs = indexSearcher.search(bqb.build(), 20, distSort);
printDocs(indexSearcher, docs, args);
indexReader.close();
}
private void printDocs(IndexSearcher indexSearcher, TopDocs docs, SpatialArgs args) throws IOException {
for (int i = 0; i < docs.totalHits; i++) {
Document doc = indexSearcher.doc(docs.scoreDocs[i].doc);
System.out.print(doc.getField("id").numericValue().intValue());
System.out.print(":" + doc.getField("name").stringValue());
//計(jì)算距離
String docStr = doc.getField(strategy.getFieldName()).stringValue();
// assume docStr is "x y" as written in newSampleDocument()
int spaceIdx = docStr.indexOf(' ');
double x = Double.parseDouble(docStr.substring(0, spaceIdx));
double y = Double.parseDouble(docStr.substring(spaceIdx + 1));
double docDistDEG = ctx.calcDistance(args.getShape().getCenter(), x, y);
System.out.print("(" + DistanceUtils.degrees2Dist(docDistDEG, DistanceUtils.EARTH_MEAN_RADIUS_KM) + "km)");
System.out.println();
}
}
}
3.測試數(shù)據(jù)
shop.json
{"id":22130905,"name":"nook諾克密室&DIY多肉(人民廣場店)","address":"浙江南路78號(hào)東新大廈216室","longitude":121.48206,"latitude":31.2288}
{"id":2871847,"name":"星巴克(江蘇店)","address":"江蘇路458號(hào)1層116","longitude":121.43091,"latitude":31.218975}
{"id":18179096,"name":"極道真人密室逃脫(人民廣場大世界總店)","address":"金陵東路569號(hào)匯通大廈804室","longitude":121.48103,"latitude":31.226982}
{"id":22676436,"name":"I high club","address":"上大路99號(hào)","longitude":121.39542,"latitude":31.312284}
{"id":16820366,"name":"小仙屋劇情密室逃脫","address":"膠州路941號(hào)長久商務(wù)中心2203室","longitude":121.436646,"latitude":31.237585}
{"id":8852374,"name":"魔方劇情真人密室逃脫(靜安店)","address":"西康路618號(hào)華通大廈13樓D座","longitude":121.446335,"latitude":31.23506}
{"id":24065790,"name":"A9真人密室逃脫(黃浦店)","address":"福州路465號(hào)上海書城6樓貝亦迪科技體驗(yàn)館","longitude":121.48146,"latitude":31.23335}
{"id":66552930,"name":"Charles' VR 虛擬現(xiàn)實(shí)體驗(yàn)館","address":"五角場大學(xué)路161號(hào)701室","longitude":121.509865,"latitude":31.304022}
{"id":8843152,"name":"iDream真人密室逃脫(百米香榭店)","address":"浙江路229號(hào)百米香榭街354店鋪","longitude":121.479,"latitude":31.233591}
{"id":11579304,"name":"1617Cafe(中山公園龍之夢服務(wù)區(qū))","address":"長寧路890號(hào)玫瑰坊1樓88B","longitude":121.41786,"latitude":31.219374}
{"id":19649586,"name":"MC精品真人密室逃脫(八佰伴店)","address":"浦東南路1088號(hào)4F-05","longitude":121.515366,"latitude":31.228285}
{"id":66350697,"name":"初魚vr咖-虛擬現(xiàn)實(shí)體驗(yàn)館","address":"大學(xué)路103號(hào)802室","longitude":121.51079,"latitude":31.304335}
{"id":3564328,"name":"Boom Cafe","address":"宣化路313號(hào)","longitude":121.42288,"latitude":31.216875}
{"id":6850935,"name":"nook諾克密室逃脫(長寧店)","address":"中山公園附近","longitude":121.4217,"latitude":31.215496}
{"id":23306435,"name":"暗黑魔盒集中營(鬼屋密室)","address":"翔殷路1099號(hào)4樓","longitude":121.51839,"latitude":31.30048}
{"id":6438722,"name":"Min魔魔島密室逃脫(中山公園店)","address":"長寧路988號(hào)花園大廈6樓606室","longitude":121.417885,"latitude":31.21871}
{"id":5411446,"name":"COSTA COFFEE(上海長寧新世界)","address":"長寧路823號(hào)1樓","longitude":121.42047,"latitude":31.21866}
{"id":7658577,"name":"因奧密室","address":"錦秋路699弄二區(qū)一排121號(hào)","longitude":121.38976,"latitude":31.32106}
{"id":17163949,"name":"aMaze真人密室逃脫","address":"長寧路988號(hào)花園大廈903","longitude":121.41791,"latitude":31.21867}
{"id":21930982,"name":"MANGOSIX(長寧龍之夢店)","address":"長寧路1018號(hào)龍之夢購物中心1樓1075號(hào)鋪","longitude":121.41745,"latitude":31.21966}
{"id":13915001,"name":"ZOOCOFFEE(定西路店)","address":"定西路1100號(hào)遼油大廈101室","longitude":121.42346,"latitude":31.2117}
{"id":8019669,"name":"貝克街5號(hào)密室逃脫","address":"長壽路181弄日月星辰2號(hào)樓1007室","longitude":121.4421,"latitude":31.241724}
{"id":67979580,"name":"Zero VR零維虛擬現(xiàn)實(shí)體驗(yàn)館","address":"定西路1310弄18號(hào)303","longitude":121.42359,"latitude":31.215818}
{"id":21374196,"name":"Dobe密室逃脫(楊浦大學(xué)路店)","address":"大學(xué)路33號(hào)701室loft37運(yùn)動(dòng)酒吧樓上","longitude":121.5117,"latitude":31.3047}
{"id":17999648,"name":"DTR夢空間密室逃脫(八佰伴店)","address":"張楊路628弄東明廣場2號(hào)樓2203室","longitude":121.52058,"latitude":31.228123}
{"id":22636011,"name":"貓小姐的店","address":"長寧路890號(hào)玫瑰坊1樓","longitude":121.41781,"latitude":31.219257}
{"id":23516373,"name":"Forest Rose Afternoon Tea","address":"長寧路890號(hào)玫瑰坊1F-72","longitude":121.418724,"latitude":31.21922}
{"id":23550163,"name":"白兔子密室逃脫","address":"長寧路405弄1號(hào)地下1層","longitude":121.427055,"latitude":31.22307}
{"id":32392280,"name":"海盜奇兵密室逃脫(五角場店)","address":"大學(xué)路33號(hào)601室loft37運(yùn)動(dòng)酒吧樓上","longitude":121.511765,"latitude":31.304789}
{"id":56588006,"name":"第五空間咖啡館","address":"長寧路1018號(hào)龍之夢購物中心4樓4202","longitude":121.41633,"latitude":31.218613}
{"id":32508745,"name":"Vital Tea(長寧龍之夢店)","address":"長寧路1018號(hào)龍之夢購物中心1F-1055","longitude":121.41703,"latitude":31.21874}
{"id":58805309,"name":"探險(xiǎn)者世界(VR體驗(yàn)館)","address":"人民廣場迪美購物中心B1層","longitude":121.47345,"latitude":31.228691}
{"id":57380950,"name":"阿拉丁真人密室逃脫(八佰伴店)","address":"張楊路628弄東明廣場3號(hào)2C","longitude":121.52024,"latitude":31.22793}
{"id":17950766,"name":"JOJO真人密室逃脫","address":"長壽路457號(hào)2樓C室","longitude":121.43657,"latitude":31.23879}
{"id":57832242,"name":"Daisy花&咖啡","address":"江蘇路54弄18號(hào)后門","longitude":121.42814,"latitude":31.223377}
{"id":28615799,"name":"Let it go臺(tái)球密室逃脫","address":"國濟(jì)路20號(hào)七樓","longitude":121.51599,"latitude":31.30196}
{"id":38092929,"name":"趣密室 & DIY手工坊","address":"石門二路333弄3號(hào)振安廣場恒安大廈22樓E座","longitude":121.4598,"latitude":31.235432}
{"id":57546152,"name":"好久不讀 long time no read","address":"愚園路1208號(hào)","longitude":121.42646,"latitude":31.219221}
{"id":66865461,"name":"VR family-虛擬現(xiàn)實(shí)體驗(yàn)館","address":"大學(xué)路錦創(chuàng)路20號(hào)1101室創(chuàng)智66商務(wù)樓內(nèi)(一兆韋德健身館旁)","longitude":121.50922,"latitude":31.304209}
{"id":9335488,"name":"77密室逃脫+真人CS(五角場店)","address":"四平路2500號(hào)東方商廈樓上金島大廈1305室","longitude":121.515465,"latitude":31.298822}
{"id":23062800,"name":"毛利偵探事務(wù)所密室逃脫","address":"大學(xué)路302號(hào)702室","longitude":121.50763,"latitude":31.30317}
{"id":50431953,"name":"顛九宮真人游戲體驗(yàn)館(楊浦店)","address":"國權(quán)路與邯鄲路交叉口","longitude":121.50096,"latitude":31.297478}
{"id":14155399,"name":"慢時(shí)光MYTIMECAFE","address":"武夷路339號(hào)","longitude":121.42406,"latitude":31.21347}
{"id":59180246,"name":"月球劇情密室逃脫(淮海中路店)","address":"普安路189號(hào)曙光大廈18D","longitude":121.47889,"latitude":31.22244}
{"id":27174604,"name":"MC精品真人密室逃脫(五角場店)","address":"翔殷路1128號(hào)8樓B4、B5","longitude":121.51691,"latitude":31.30103}
{"id":32640417,"name":"西塞密室(長寧店)","address":"愚園路1391號(hào)3樓","longitude":121.42288,"latitude":31.218843}
{"id":23403568,"name":"暗黑迷宮第三季","address":"南京西路1788號(hào)1788廣場F201","longitude":121.44376,"latitude":31.22278}
{"id":7045554,"name":"巴黎春天新世界酒店濃咖啡","address":"定西路1555號(hào)酒店2樓","longitude":121.4211,"latitude":31.218554}
{"id":24899623,"name":"GIVE ME FIVE劇情密室逃脫(大學(xué)路店)","address":"大學(xué)路錦創(chuàng)路26號(hào)1102室創(chuàng)智66商務(wù)樓內(nèi)","longitude":121.50918,"latitude":31.30425}
{"id":67335522,"name":"nook諾克劇情密室 & VR虛擬現(xiàn)實(shí)體驗(yàn)館(五角場店)","address":"大學(xué)路錦創(chuàng)路26號(hào)1602室創(chuàng)智66商務(wù)樓內(nèi)","longitude":121.509315,"latitude":31.304174}
{"id":4275877,"name":"Home Garden","address":"安化路492號(hào)德必易園多媒體創(chuàng)意園區(qū)106室","longitude":121.4202,"latitude":31.215342}
{"id":18593150,"name":"TIK TOK","address":"江蘇路458號(hào)112室舜元企業(yè)發(fā)展大廈","longitude":121.43106,"latitude":31.218548}
{"id":22447664,"name":"Running基地","address":"軍工路100號(hào)","longitude":121.558266,"latitude":31.281694}
{"id":24678174,"name":"太平洋咖啡(兆豐廣場店)","address":"長寧路999號(hào)兆豐廣場","longitude":121.41788,"latitude":31.21765}
{"id":57439748,"name":"essence casa","address":"愚園路1329號(hào)","longitude":121.42449,"latitude":31.21873}
{"id":65835399,"name":"大華虎城第三空間","address":"白麗路61號(hào)","longitude":121.35216,"latitude":31.27899}
{"id":19671618,"name":"FullHouse桌游棋牌密室(南京西路店)","address":"大田路129號(hào)嘉發(fā)大廈A座25樓G","longitude":121.46391,"latitude":31.23294}
{"id":23740568,"name":"aMaze真人密室逃脫(人民廣場大世界店)","address":"云南南路180號(hào)淮云大廈8樓","longitude":121.48128,"latitude":31.2265}
{"id":22132387,"name":"智源咖啡(中山公園店)","address":"安化路492號(hào)易園","longitude":121.42034,"latitude":31.21529}
{"id":56890263,"name":"跑男開始了 runningman(公司活動(dòng),年會(huì)撕名牌)","address":"淮海中路","longitude":121.49525,"latitude":31.22792}
{"id":18636516,"name":"ASA亞撒真人密室逃脫","address":"武夷路418弄(近定西路)1號(hào)武定大廈203室","longitude":121.421974,"latitude":31.212627}
{"id":5857955,"name":"Crazycube顛九宮密室逃脫(大學(xué)路店)","address":"創(chuàng)智坊大學(xué)路302號(hào)701室","longitude":121.50754,"latitude":31.303108}
{"id":2036581,"name":"星巴克(龍之夢2店)","address":"長寧路1018號(hào)龍之夢購物中心1樓1073號(hào)鋪","longitude":121.416916,"latitude":31.218727}
{"id":13913129,"name":"Captain.C真人密室逃脫","address":"延平路69號(hào)延平大廈701室","longitude":121.44161,"latitude":31.227833}
{"id":57682702,"name":"aMaze真人密室逃脫(五角場店)","address":"大學(xué)路292號(hào)602室","longitude":121.50777,"latitude":31.30327}
4.測試結(jié)果
以下為分別搜索周圍3公里內(nèi)的密室和咖啡店的結(jié)果。
17163949:aMaze真人密室逃脫(0.0km)
6438722:Min魔魔島密室逃脫(中山公園店)(0.005043281377521635km)
32640417:西塞密室(長寧店)(0.47300570633073574km)
6850935:nook諾克密室逃脫(長寧店)(0.5044378650402169km)
18636516:ASA亞撒真人密室逃脫(0.7751646578452988km)
23550163:白兔子密室逃脫(0.9977952318745087km)
13913129:Captain.C真人密室逃脫(2.473229285495286km)
16820366:小仙屋劇情密室逃脫(2.7563385153155853km)
17950766:JOJO真人密室逃脫(2.855389720759213km)
----------------
24678174:太平洋咖啡(兆豐廣場店)(0.11345485407738468km)
7045554:巴黎春天新世界酒店濃咖啡(0.30362262844238574km)
22132387:智源咖啡(中山公園店)(0.44119592062398144km)
57832242:Daisy花&咖啡(1.1046485391701188km)
5.參考資料
[url=http://baobeituping.iteye.com/blog/2214857]使用Lucene-Spatial實(shí)現(xiàn)集成地理位置的全文檢索[/url]
[url=http://iamyida.iteye.com/blog/2204455]Lucene5學(xué)習(xí)之Spatial地理位置搜索[/url]
<properties>
<lib.lucene.version>6.1.0</lib.lucene.version>
</properties>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.8.1</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>${lib.lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>${lib.lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-spatial</artifactId>
<version>${lib.lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-spatial-extras</artifactId>
<version>${lib.lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-smartcn</artifactId>
<version>${lib.lucene.version}</version>
</dependency>
2.直接上代碼
package org.xpen.hello.search.lucene;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.NumericDocValuesField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TermQuery;
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.RAMDirectory;
import org.junit.Test;
import org.locationtech.spatial4j.context.SpatialContext;
import org.locationtech.spatial4j.distance.DistanceUtils;
import org.locationtech.spatial4j.shape.Point;
import org.locationtech.spatial4j.shape.Shape;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Lucene spatial演示
* 出處:官方j(luò)unit代碼
*/
public class SpatialExample {
@Test
public void test() throws Exception {
init();
indexPoints();
search();
}
/** Spatial4j上下文 */
private SpatialContext ctx;// "ctx" is the conventional variable name
/** 提供索引和查詢模型的策略接口 */
private SpatialStrategy strategy;
/** 索引目錄 */
private Directory directory;
protected void init() {
// SpatialContext也可以通過SpatialContextFactory工廠類來構(gòu)建
this.ctx = SpatialContext.GEO;
//網(wǎng)格最大11層, geohash的精度
int maxLevels = 11;
//Spatial Tiers
SpatialPrefixTree grid = new GeohashPrefixTree(ctx, maxLevels);
this.strategy = new RecursivePrefixTreeStrategy(grid, "myGeoField");
this.directory = new RAMDirectory();
}
private void indexPoints() throws Exception {
IndexWriterConfig iwConfig = new IndexWriterConfig(new SmartChineseAnalyzer());
IndexWriter indexWriter = new IndexWriter(directory, iwConfig);
JsonFactory jsonFactory = new JsonFactory();
jsonFactory.enable(JsonParser.Feature.ALLOW_COMMENTS);
ObjectMapper mapper = new ObjectMapper(jsonFactory);
BufferedReader br = new BufferedReader(new InputStreamReader(
SpatialExample.class.getClassLoader().getResourceAsStream("search/lucene/shop.json")));
String line = null;
while ((line = br.readLine()) != null) {
ShopBean shopBean = mapper.readValue(line, ShopBean.class);
//這里的x,y即經(jīng)緯度,x為Longitude(經(jīng)度),y為Latitude(緯度)
Document document = newSampleDocument(shopBean.getId(), shopBean.getName(), ctx.makePoint(shopBean.getLongitude(), shopBean.getLatitude()));
indexWriter.addDocument(document);
}
indexWriter.close();
}
private Document newSampleDocument(int id, String title, Shape... shapes) {
Document doc = new Document();
doc.add(new StoredField("id", id));
doc.add(new NumericDocValuesField("id", id));
doc.add(new TextField("name", title, Store.YES));
// Potentially more than one shape in this field is supported by some
// strategies; see the javadocs of the SpatialStrategy impl to see.
for (Shape shape : shapes) {
for (Field f : strategy.createIndexableFields(shape)) {
doc.add(f);
}
// store it too; the format is up to you
// (assume point in this example)
Point pt = (Point) shape;
doc.add(new StoredField(strategy.getFieldName(), pt.getX() + " " + pt.getY()));
}
return doc;
}
private void search() throws Exception {
searchInner("密室");
System.out.println("----------------");
searchInner("咖啡");
}
private void searchInner(String keyword) throws Exception {
IndexReader indexReader = DirectoryReader.open(directory);
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
// --Filter by circle (<= distance from a point)
// Search with circle
// note: SpatialArgs can be parsed from a string
Point pt = ctx.makePoint(121.41791, 31.21867);
// the distance in km
ValueSource valueSource = strategy.makeDistanceValueSource(pt, DistanceUtils.DEG_TO_KM);
//按距離由近及遠(yuǎn)排序
Sort distSort = new Sort(valueSource.getSortField(false)).rewrite(indexSearcher); // false=asc dist
SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects,
ctx.makeCircle(pt, DistanceUtils.dist2Degrees(3.0, DistanceUtils.EARTH_MEAN_RADIUS_KM)));
Query query = strategy.makeQuery(args);
BooleanQuery.Builder bqb = new BooleanQuery.Builder();
bqb.add(query, BooleanClause.Occur.MUST);
bqb.add(new TermQuery(new Term("name", keyword)), BooleanClause.Occur.MUST);
TopDocs docs = indexSearcher.search(bqb.build(), 20, distSort);
printDocs(indexSearcher, docs, args);
indexReader.close();
}
private void printDocs(IndexSearcher indexSearcher, TopDocs docs, SpatialArgs args) throws IOException {
for (int i = 0; i < docs.totalHits; i++) {
Document doc = indexSearcher.doc(docs.scoreDocs[i].doc);
System.out.print(doc.getField("id").numericValue().intValue());
System.out.print(":" + doc.getField("name").stringValue());
//計(jì)算距離
String docStr = doc.getField(strategy.getFieldName()).stringValue();
// assume docStr is "x y" as written in newSampleDocument()
int spaceIdx = docStr.indexOf(' ');
double x = Double.parseDouble(docStr.substring(0, spaceIdx));
double y = Double.parseDouble(docStr.substring(spaceIdx + 1));
double docDistDEG = ctx.calcDistance(args.getShape().getCenter(), x, y);
System.out.print("(" + DistanceUtils.degrees2Dist(docDistDEG, DistanceUtils.EARTH_MEAN_RADIUS_KM) + "km)");
System.out.println();
}
}
}
3.測試數(shù)據(jù)
shop.json
{"id":22130905,"name":"nook諾克密室&DIY多肉(人民廣場店)","address":"浙江南路78號(hào)東新大廈216室","longitude":121.48206,"latitude":31.2288}
{"id":2871847,"name":"星巴克(江蘇店)","address":"江蘇路458號(hào)1層116","longitude":121.43091,"latitude":31.218975}
{"id":18179096,"name":"極道真人密室逃脫(人民廣場大世界總店)","address":"金陵東路569號(hào)匯通大廈804室","longitude":121.48103,"latitude":31.226982}
{"id":22676436,"name":"I high club","address":"上大路99號(hào)","longitude":121.39542,"latitude":31.312284}
{"id":16820366,"name":"小仙屋劇情密室逃脫","address":"膠州路941號(hào)長久商務(wù)中心2203室","longitude":121.436646,"latitude":31.237585}
{"id":8852374,"name":"魔方劇情真人密室逃脫(靜安店)","address":"西康路618號(hào)華通大廈13樓D座","longitude":121.446335,"latitude":31.23506}
{"id":24065790,"name":"A9真人密室逃脫(黃浦店)","address":"福州路465號(hào)上海書城6樓貝亦迪科技體驗(yàn)館","longitude":121.48146,"latitude":31.23335}
{"id":66552930,"name":"Charles' VR 虛擬現(xiàn)實(shí)體驗(yàn)館","address":"五角場大學(xué)路161號(hào)701室","longitude":121.509865,"latitude":31.304022}
{"id":8843152,"name":"iDream真人密室逃脫(百米香榭店)","address":"浙江路229號(hào)百米香榭街354店鋪","longitude":121.479,"latitude":31.233591}
{"id":11579304,"name":"1617Cafe(中山公園龍之夢服務(wù)區(qū))","address":"長寧路890號(hào)玫瑰坊1樓88B","longitude":121.41786,"latitude":31.219374}
{"id":19649586,"name":"MC精品真人密室逃脫(八佰伴店)","address":"浦東南路1088號(hào)4F-05","longitude":121.515366,"latitude":31.228285}
{"id":66350697,"name":"初魚vr咖-虛擬現(xiàn)實(shí)體驗(yàn)館","address":"大學(xué)路103號(hào)802室","longitude":121.51079,"latitude":31.304335}
{"id":3564328,"name":"Boom Cafe","address":"宣化路313號(hào)","longitude":121.42288,"latitude":31.216875}
{"id":6850935,"name":"nook諾克密室逃脫(長寧店)","address":"中山公園附近","longitude":121.4217,"latitude":31.215496}
{"id":23306435,"name":"暗黑魔盒集中營(鬼屋密室)","address":"翔殷路1099號(hào)4樓","longitude":121.51839,"latitude":31.30048}
{"id":6438722,"name":"Min魔魔島密室逃脫(中山公園店)","address":"長寧路988號(hào)花園大廈6樓606室","longitude":121.417885,"latitude":31.21871}
{"id":5411446,"name":"COSTA COFFEE(上海長寧新世界)","address":"長寧路823號(hào)1樓","longitude":121.42047,"latitude":31.21866}
{"id":7658577,"name":"因奧密室","address":"錦秋路699弄二區(qū)一排121號(hào)","longitude":121.38976,"latitude":31.32106}
{"id":17163949,"name":"aMaze真人密室逃脫","address":"長寧路988號(hào)花園大廈903","longitude":121.41791,"latitude":31.21867}
{"id":21930982,"name":"MANGOSIX(長寧龍之夢店)","address":"長寧路1018號(hào)龍之夢購物中心1樓1075號(hào)鋪","longitude":121.41745,"latitude":31.21966}
{"id":13915001,"name":"ZOOCOFFEE(定西路店)","address":"定西路1100號(hào)遼油大廈101室","longitude":121.42346,"latitude":31.2117}
{"id":8019669,"name":"貝克街5號(hào)密室逃脫","address":"長壽路181弄日月星辰2號(hào)樓1007室","longitude":121.4421,"latitude":31.241724}
{"id":67979580,"name":"Zero VR零維虛擬現(xiàn)實(shí)體驗(yàn)館","address":"定西路1310弄18號(hào)303","longitude":121.42359,"latitude":31.215818}
{"id":21374196,"name":"Dobe密室逃脫(楊浦大學(xué)路店)","address":"大學(xué)路33號(hào)701室loft37運(yùn)動(dòng)酒吧樓上","longitude":121.5117,"latitude":31.3047}
{"id":17999648,"name":"DTR夢空間密室逃脫(八佰伴店)","address":"張楊路628弄東明廣場2號(hào)樓2203室","longitude":121.52058,"latitude":31.228123}
{"id":22636011,"name":"貓小姐的店","address":"長寧路890號(hào)玫瑰坊1樓","longitude":121.41781,"latitude":31.219257}
{"id":23516373,"name":"Forest Rose Afternoon Tea","address":"長寧路890號(hào)玫瑰坊1F-72","longitude":121.418724,"latitude":31.21922}
{"id":23550163,"name":"白兔子密室逃脫","address":"長寧路405弄1號(hào)地下1層","longitude":121.427055,"latitude":31.22307}
{"id":32392280,"name":"海盜奇兵密室逃脫(五角場店)","address":"大學(xué)路33號(hào)601室loft37運(yùn)動(dòng)酒吧樓上","longitude":121.511765,"latitude":31.304789}
{"id":56588006,"name":"第五空間咖啡館","address":"長寧路1018號(hào)龍之夢購物中心4樓4202","longitude":121.41633,"latitude":31.218613}
{"id":32508745,"name":"Vital Tea(長寧龍之夢店)","address":"長寧路1018號(hào)龍之夢購物中心1F-1055","longitude":121.41703,"latitude":31.21874}
{"id":58805309,"name":"探險(xiǎn)者世界(VR體驗(yàn)館)","address":"人民廣場迪美購物中心B1層","longitude":121.47345,"latitude":31.228691}
{"id":57380950,"name":"阿拉丁真人密室逃脫(八佰伴店)","address":"張楊路628弄東明廣場3號(hào)2C","longitude":121.52024,"latitude":31.22793}
{"id":17950766,"name":"JOJO真人密室逃脫","address":"長壽路457號(hào)2樓C室","longitude":121.43657,"latitude":31.23879}
{"id":57832242,"name":"Daisy花&咖啡","address":"江蘇路54弄18號(hào)后門","longitude":121.42814,"latitude":31.223377}
{"id":28615799,"name":"Let it go臺(tái)球密室逃脫","address":"國濟(jì)路20號(hào)七樓","longitude":121.51599,"latitude":31.30196}
{"id":38092929,"name":"趣密室 & DIY手工坊","address":"石門二路333弄3號(hào)振安廣場恒安大廈22樓E座","longitude":121.4598,"latitude":31.235432}
{"id":57546152,"name":"好久不讀 long time no read","address":"愚園路1208號(hào)","longitude":121.42646,"latitude":31.219221}
{"id":66865461,"name":"VR family-虛擬現(xiàn)實(shí)體驗(yàn)館","address":"大學(xué)路錦創(chuàng)路20號(hào)1101室創(chuàng)智66商務(wù)樓內(nèi)(一兆韋德健身館旁)","longitude":121.50922,"latitude":31.304209}
{"id":9335488,"name":"77密室逃脫+真人CS(五角場店)","address":"四平路2500號(hào)東方商廈樓上金島大廈1305室","longitude":121.515465,"latitude":31.298822}
{"id":23062800,"name":"毛利偵探事務(wù)所密室逃脫","address":"大學(xué)路302號(hào)702室","longitude":121.50763,"latitude":31.30317}
{"id":50431953,"name":"顛九宮真人游戲體驗(yàn)館(楊浦店)","address":"國權(quán)路與邯鄲路交叉口","longitude":121.50096,"latitude":31.297478}
{"id":14155399,"name":"慢時(shí)光MYTIMECAFE","address":"武夷路339號(hào)","longitude":121.42406,"latitude":31.21347}
{"id":59180246,"name":"月球劇情密室逃脫(淮海中路店)","address":"普安路189號(hào)曙光大廈18D","longitude":121.47889,"latitude":31.22244}
{"id":27174604,"name":"MC精品真人密室逃脫(五角場店)","address":"翔殷路1128號(hào)8樓B4、B5","longitude":121.51691,"latitude":31.30103}
{"id":32640417,"name":"西塞密室(長寧店)","address":"愚園路1391號(hào)3樓","longitude":121.42288,"latitude":31.218843}
{"id":23403568,"name":"暗黑迷宮第三季","address":"南京西路1788號(hào)1788廣場F201","longitude":121.44376,"latitude":31.22278}
{"id":7045554,"name":"巴黎春天新世界酒店濃咖啡","address":"定西路1555號(hào)酒店2樓","longitude":121.4211,"latitude":31.218554}
{"id":24899623,"name":"GIVE ME FIVE劇情密室逃脫(大學(xué)路店)","address":"大學(xué)路錦創(chuàng)路26號(hào)1102室創(chuàng)智66商務(wù)樓內(nèi)","longitude":121.50918,"latitude":31.30425}
{"id":67335522,"name":"nook諾克劇情密室 & VR虛擬現(xiàn)實(shí)體驗(yàn)館(五角場店)","address":"大學(xué)路錦創(chuàng)路26號(hào)1602室創(chuàng)智66商務(wù)樓內(nèi)","longitude":121.509315,"latitude":31.304174}
{"id":4275877,"name":"Home Garden","address":"安化路492號(hào)德必易園多媒體創(chuàng)意園區(qū)106室","longitude":121.4202,"latitude":31.215342}
{"id":18593150,"name":"TIK TOK","address":"江蘇路458號(hào)112室舜元企業(yè)發(fā)展大廈","longitude":121.43106,"latitude":31.218548}
{"id":22447664,"name":"Running基地","address":"軍工路100號(hào)","longitude":121.558266,"latitude":31.281694}
{"id":24678174,"name":"太平洋咖啡(兆豐廣場店)","address":"長寧路999號(hào)兆豐廣場","longitude":121.41788,"latitude":31.21765}
{"id":57439748,"name":"essence casa","address":"愚園路1329號(hào)","longitude":121.42449,"latitude":31.21873}
{"id":65835399,"name":"大華虎城第三空間","address":"白麗路61號(hào)","longitude":121.35216,"latitude":31.27899}
{"id":19671618,"name":"FullHouse桌游棋牌密室(南京西路店)","address":"大田路129號(hào)嘉發(fā)大廈A座25樓G","longitude":121.46391,"latitude":31.23294}
{"id":23740568,"name":"aMaze真人密室逃脫(人民廣場大世界店)","address":"云南南路180號(hào)淮云大廈8樓","longitude":121.48128,"latitude":31.2265}
{"id":22132387,"name":"智源咖啡(中山公園店)","address":"安化路492號(hào)易園","longitude":121.42034,"latitude":31.21529}
{"id":56890263,"name":"跑男開始了 runningman(公司活動(dòng),年會(huì)撕名牌)","address":"淮海中路","longitude":121.49525,"latitude":31.22792}
{"id":18636516,"name":"ASA亞撒真人密室逃脫","address":"武夷路418弄(近定西路)1號(hào)武定大廈203室","longitude":121.421974,"latitude":31.212627}
{"id":5857955,"name":"Crazycube顛九宮密室逃脫(大學(xué)路店)","address":"創(chuàng)智坊大學(xué)路302號(hào)701室","longitude":121.50754,"latitude":31.303108}
{"id":2036581,"name":"星巴克(龍之夢2店)","address":"長寧路1018號(hào)龍之夢購物中心1樓1073號(hào)鋪","longitude":121.416916,"latitude":31.218727}
{"id":13913129,"name":"Captain.C真人密室逃脫","address":"延平路69號(hào)延平大廈701室","longitude":121.44161,"latitude":31.227833}
{"id":57682702,"name":"aMaze真人密室逃脫(五角場店)","address":"大學(xué)路292號(hào)602室","longitude":121.50777,"latitude":31.30327}
4.測試結(jié)果
以下為分別搜索周圍3公里內(nèi)的密室和咖啡店的結(jié)果。
17163949:aMaze真人密室逃脫(0.0km)
6438722:Min魔魔島密室逃脫(中山公園店)(0.005043281377521635km)
32640417:西塞密室(長寧店)(0.47300570633073574km)
6850935:nook諾克密室逃脫(長寧店)(0.5044378650402169km)
18636516:ASA亞撒真人密室逃脫(0.7751646578452988km)
23550163:白兔子密室逃脫(0.9977952318745087km)
13913129:Captain.C真人密室逃脫(2.473229285495286km)
16820366:小仙屋劇情密室逃脫(2.7563385153155853km)
17950766:JOJO真人密室逃脫(2.855389720759213km)
----------------
24678174:太平洋咖啡(兆豐廣場店)(0.11345485407738468km)
7045554:巴黎春天新世界酒店濃咖啡(0.30362262844238574km)
22132387:智源咖啡(中山公園店)(0.44119592062398144km)
57832242:Daisy花&咖啡(1.1046485391701188km)
5.參考資料
[url=http://baobeituping.iteye.com/blog/2214857]使用Lucene-Spatial實(shí)現(xiàn)集成地理位置的全文檢索[/url]
[url=http://iamyida.iteye.com/blog/2204455]Lucene5學(xué)習(xí)之Spatial地理位置搜索[/url]
總結(jié)
以上是生活随笔為你收集整理的lucene spatial 6.1搜索附近的饭店的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 常用电平标准 TTL、CMOS、LVTT
- 下一篇: emmc 分区管理