使用Lucene-Spatial实现地理位置检索.doc_第1页
使用Lucene-Spatial实现地理位置检索.doc_第2页
使用Lucene-Spatial实现地理位置检索.doc_第3页
使用Lucene-Spatial实现地理位置检索.doc_第4页
使用Lucene-Spatial实现地理位置检索.doc_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

使用Lucene-Spatial实现集成地理位置检索Lucene通过Spatial包提供了对基于地理位置的全文检索的支持,最典型的应用场景就是:“搜索中关村附近1公里内的火锅店,并按远近排序”。使用Lucene-Spatial添加对地理位置的支持,和之前普通文本搜索主要有两点区别: 1. 将坐标信息转化为笛卡尔层,建立索引view plaincopy to clipboardprint?1. privatevoidindexLocation(Documentdocument,JSONObjectjo)2. throwsException3. 4. doublelongitude=jo.getDouble(longitude);5. doublelatitude=jo.getDouble(latitude);6. 7. document.add(newField(lat,NumericUtils8. .doubleToPrefixCoded(latitude),Field.Store.YES,9. Field.Index.NOT_ANALYZED);10. document.add(newField(lng,NumericUtils11. .doubleToPrefixCoded(longitude),Field.Store.YES,12. Field.Index.NOT_ANALYZED);13. 14. for(inttier=startTier;tier=endTier;tier+)15. ctp=newCartesianTierPlotter(tier,projector,16. CartesianTierPlotter.DEFALT_FIELD_PREFIX);17. finaldoubleboxId=ctp.getTierBoxId(latitude,longitude);18. document.add(newField(ctp.getTierFieldName(),NumericUtils19. .doubleToPrefixCoded(boxId),Field.Store.YES,20. Field.Index.NOT_ANALYZED_NO_NORMS);21. 22. 2. 搜索时,指定使用DistanceQueryFilter view plaincopy to clipboardprint?1. DistanceQueryBuilderdq=newDistanceQueryBuilder(latitude,2. longitude,miles,lat,lng,3. CartesianTierPlotter.DEFALT_FIELD_PREFIX,true,startTier,4. endTier);5. DistanceFieldComparatorSourcedsort=newDistanceFieldComparatorSource(6. dq.getDistanceFilter();7. Sortsort=newSort(newSortField(geo_distance,dsort); 下面是基于Lucene3.2.0和JUnit4.8.2的完整代码。 view plaincopy to clipboardprint?1. 2. 3. junit4. junit5. 4.8.26. jar7. test8. 9. 10. org.apache.lucene11. lucene-core12. 3.2.013. jar14. compile15. 16. 17. org.apache.lucene18. lucene-spatial19. 3.2.020. jar21. compile22. 23. 24. org.json25. json26. 2010090327. jar28. compile29. 30. 首先准备测试用的数据: view plaincopy to clipboardprint?1. id:12,title:时尚码头美容美发热烫特价,longitude:116.3838183,latitude:39.96290152. id:17,title:审美个人美容美发套餐,longitude:116.386564,latitude:39.9661023. id:23,title:海底捞吃300送300,longitude:116.38629,latitude:39.96295734. id:26,title:仅98元!享原价335元李老爹,longitude:116.3846175,latitude:39.96291255. id:29,title:都美造型烫染美发护理套餐,longitude:116.38629,latitude:39.96295736. id:30,title:仅售55元!原价80元的老舍茶馆相声下午场,longitude:116.0799914,latitude:39.96553917. id:33,title:仅售55元!原价80元的新笑声客栈早场,longitude:116.0799914,latitude:39.96553918. id:34,title:仅售39元(红色礼盒)!原价80元的平谷桃,longitude:116.0799914,latitude:39.96553919. id:46,title:仅售38元!原价180元地质礼堂白雪公主,longitude:116.0799914,latitude:39.965539110. id:49,title:仅99元!享原价342.7元自助餐,longitude:116.0799914,latitude:39.965539111. id:58,title:桑海教育暑期学生报名培训九折优惠券,longitude:116.0799914,latitude:39.965539112. id:59,title:全国发货:仅29元!贝玲妃超模粉红高光光,longitude:116.0799914,latitude:39.965539113. id:65,title:海之屿生态水族用品店抵用券,longitude:116.0799914,latitude:39.965539114. id:67,title:小区东门时尚烫染个人护理美发套餐,longitude:116.3799914,latitude:39.965539115. id:74,title:郭德纲相声专辑CD套装,longitude:116.0799914,latitude:39.9655391 根据上面的测试数据,编写测试用例,分别搜索坐标(116.3838183, 39.9629015)3千米以内的“美发”和全部内容,分别得到的结果应该是4条和6条。 view plaincopy to clipboardprint?1. importstaticorg.junit.Assert.assertEquals;2. importstaticorg.junit.Assert.fail;3. 4. importjava.util.List;5. 6. importorg.junit.Test;7. 8. publicclassLuceneSpatialTest9. 10. privatestaticLuceneSpatialspatialSearcher=newLuceneSpatial();11. 12. Test13. publicvoidtestSearch()14. try15. longstart=System.currentTimeMillis();16. Listresults=spatialSearcher.search(美发,116.3838183,39.9629015,3.0);17. System.out.println(results.size()18. +个匹配结果,共耗时19. +(System.currentTimeMillis()-start)+毫秒。n);20. assertEquals(4,results.size();21. catch(Exceptione)22. fail(Exceptionoccurs.);23. e.printStackTrace();24. 25. 26. 27. Test28. publicvoidtestSearchWithoutKeyword()29. try30. longstart=System.currentTimeMillis();31. Listresults=spatialSearcher.search(null,116.3838183,39.9629015,3.0);32. System.out.println(results.size()33. +个匹配结果,共耗时34. +(System.currentTimeMillis()-start)+毫秒.n);35. assertEquals(6,results.size();36. catch(Exceptione)37. fail(Exceptionoccurs.);38. e.printStackTrace();39. 40. 41. 下面是LuceneSpatial类,在构造函数中初始化变量和创建索引: view plaincopy to clipboardprint?1. publicclassLuceneSpatial2. 3. privateAnalyzeranalyzer;4. privateIndexWriterwriter;5. privateFSDirectoryindexDirectory;6. privateIndexSearcherindexSearcher;7. privateIndexReaderindexReader;8. privateStringindexPath=c:/lucene-spatial;9. 10. /Spatial 11. privateIProjectorprojector;12. privateCartesianTierPlotterctp;13. publicstaticfinaldoubleRATE_MILE_TO_KM=1.609344;/英里和公里的比率 14. publicstaticfinalStringLAT_FIELD=lat;15. publicstaticfinalStringLON_FIELD=lng;16. privatestaticfinaldoubleMAX_RANGE=15.0;/索引支持的最大范围,单位是千米 17. privatestaticfinaldoubleMIN_RANGE=3.0;/索引支持的最小范围,单位是千米 18. privateintstartTier;19. privateintendTier;20. 21. publicLuceneSpatial()22. try23. init();24. catch(Exceptione)25. e.printStackTrace();26. 27. 28. 29. privatevoidinit()throwsException30. initializeSpatialOptions();31. 32. analyzer=newStandardAnalyzer(Version.LUCENE_32);33. 34. Filepath=newFile(indexPath);35. 36. booleanisNeedCreateIndex=false;37. 38. if(path.exists()&!path.isDirectory()39. thrownewException(Specifiedpathisnotadirectory);40. 41. if(!path.exists()42. path.mkdirs();43. isNeedCreateIndex=true;44. 45. 46. indexDirectory=FSDirectory.open(newFile(indexPath);47. 48. /建立索引 49. if(isNeedCreateIndex)50. IndexWriterConfigindexWriterConfig=newIndexWriterConfig(51. Version.LUCENE_32,analyzer);52. indexWriterConfig.setOpenMode(OpenMode.CREATE_OR_APPEND);53. writer=newIndexWriter(indexDirectory,indexWriterConfig);54. buildIndex();55. 56. 57. indexReader=IndexReader.open(indexDirectory,true);58. indexSearcher=newIndexSearcher(indexReader);59. 60. 61. 62. SuppressWarnings(deprecation)63. privatevoidinitializeSpatialOptions()64. projector=newSinusoidalProjector();65. ctp=newCartesianTierPlotter(0,projector,66. CartesianTierPlotter.DEFALT_FIELD_PREFIX);67. startTier=ctp.bestFit(MAX_RANGE/RATE_MILE_TO_KM);68. endTier=ctp.bestFit(MIN_RANGE/RATE_MILE_TO_KM);69. 70. 71. 72. 73. privateintmile2Meter(doublemiles)74. doubledMeter=miles*RATE_MILE_TO_KM*1000;75. 76. return(int)dMeter;77. 78. 79. privatedoublekm2Mile(doublekm)80. returnkm/RATE_MILE_TO_KM;81. 创建索引的具体实现:view plaincopy to clipboardprint?1. privatevoidbuildIndex()2. BufferedReaderbr=null;3. try4. /逐行添加测试数据到索引中,测试数据文件和源文件在同一个目录下 5. br=newBufferedReader(newInputStreamReader(6. LuceneSpatial.class.getResourceAsStream(data);7. Stringline=null;8. while(line=br.readLine()!=null)9. index(newJSONObject(line);10. 11. 12. mit();13. catch(Exceptione)14. e.printStackTrace();15. finally16. if(br!=null)17. try18. br.close();19. catch(IOExceptione)20. e.printStackTrace();21. 22. 23. 24. 25. 26. privatevoidindex(JSONObjectjo)throwsException27. Documentdoc=newDocument();28. 29. doc.add(newField(id,jo.getString(id),Field.Store.YES,30. Field.Index.ANALYZED);31. 32. doc.add(newField(title,jo.getString(title),Field.Store.YES,33. Field.Index.ANALYZED);34. 35. /将位置信息添加到索引中 36. indexLocation(doc,jo);37. 38. writer.addDocument(doc);39. 40. 41. privatevoidindexLocation(Documentdocument,JSONObjectjo)42. throwsException43. 44. doublelongitude=jo.getDouble(longitude);45. doublelatitude=jo.getDouble(latitude);46. 47. document.add(newField(lat,NumericUtils48. .doubleToPrefixCoded(latitude),Field.Store.YES,49. Field.Index.NOT_ANALYZED);50. document.add(newField(lng,NumericUtils51. .doubleToPrefixCoded(longitude),Field.Store.YES,52. Field.Index.NOT_ANALYZED);53. 54. for(inttier=startTier;tier=endTier;tier+)55. ctp=newCartesianTierPlotter(tier,projector,56. CartesianTierPlotter.DEFALT_FIELD_PREFIX);57. finaldoubleboxId=ctp.getTierBoxId(latitude,longitude);58. document.add(newField(ctp.getTierFieldName(),NumericUtils59. .doubleToPrefixCoded(boxId),Field.Store.YES,60. Field.Index.NOT_ANALYZED_NO_NORMS);61. 62. 搜索的具体实现: view plaincopy to clipboardprint?1. publicListsearch(Stringkeyword,doublelongitude,2. doublelatitude,doublerange)throwsException3. Listresult=newArrayList();4. 5. doublemiles=km2Mile(range);6. 7. DistanceQueryBuilderdq=newDistanceQueryBuilder(latitude,8. longitude,miles,lat,lng,9. CartesianTierPlotter.DEFALT_FIELD_PREFIX,true,startTier,10. endTier);11. 12. /按照距离排序 13. DistanceFieldComparatorSourcedsort=newDistanceFieldComparatorSource(14. dq.getDistanceFilter();15. Sortsort=newSort(newSortField(geo_distance,dsort);16. 17. Queryquery=buildQuery(keyword);18. 19. /搜索结果 20. TopDocshits=indexSearcher.search(query,dq.getFilter(),21. Integer.MAX_VALUE,sort);22. /获得各条结果相对应的距离 23. Mapdistances=dq.getDistanceFilter()24. .getDistances();25. 26. for(inti=0;ihits.totalHits;i+)27. finalintdocID=hits.scoreDocsi.doc;28. 29. finalDocumentdoc=indexSearcher.doc(docID);30. 31. finalStringBuilderbuilder=newStringBuilder();32. builder.append(找到了:)33. .append(doc.get(title)34. .append(,距离:)35. .append(mile2Meter(distances.get(docID)36. .append(米。);37. System.out.println(builder.toS

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论