http://ju.outofmemory.cn/entry/711
本文将继续介绍基于Solr的地理位置搜索的第二种实现方案
CartesianTiers+GeoHash
从基于Solr的地理位置搜索(2)文章中可以看到完全基于GeoHash的查询过滤,将完全遍历整个docment文档,从效率上来看并不太合适,所以结合笛卡尔层后,能有效缩减少过滤范围,从性能上能很大程度的提高。
构建索引阶段:
String geoHash = GeoHashUtils.encode(latitude, longitude);
docment.addField(“geohash”, geoHash);
//Cartesian Tiers
int tier = START_TIER;//开始构建索引的层数
//Create a bunch of tiers, each deeper level has more precision
//将一条记录的经纬度对应全部笛卡尔层的tierBoxId作为域值构建索引
for (CartesianTierPlotter plotter : plotters) {
docment.addField(“tier_” + tier , plotter.getTierBoxId(latitude, longitude));
tier++;
}
看到这里大家肯定明白了。越相近的经纬度在同层肯定会在同一个网格中,所以他们存储的tierBoxId就会是一样。那么查询的时候通过经纬度对应 层的tierBoxId,也就能找到相同层域的docId,但是如果给定的的查询范围大,可能需要将若干层的所属网格的docId都查到。
整个查询过程是先通过笛卡尔层将若干个网格涉及的DocList存入bitSet,如下代码所示:
public DocIdSet getDocIdSet(final IndexReader reader) throws IOException {
final FixedBitSet bits = new FixedBitSet(reader.maxDoc());
final TermDocs termDocs = reader.termDocs();
//需要查询的若干层网格的boxIdList,当然至此已经过滤掉不需要查询层的boxIdList
final List<Double> area = shape.getArea();
int sz = area.size();
final Term term = new Term(fieldName);//
// iterate through each boxid
for (int i =0; i< sz; i++) {
double boxId = area.get(i).doubleValue();
termDocs.seek(term.createTerm(NumericUtils.doubleToPrefixCoded(boxId)));
// iterate through all documents
// which have this boxId
//遍历所有包含给定boxId的docList,并将其放入bitset
while (termDocs.next()) {
bits.set(termDocs.doc());
}
}
return bits;
}
介绍完笛卡尔层的计算后,接下来介绍笛卡尔层过滤后返还的bitset如何和geoHash结合,从实现上讲其实很简单,就是将通过笛卡尔层过滤的 数据结果集合 依次遍历计算其与查询给定的经纬度坐标的球面距离,同时将该计算距离和查询指定范围距离进行比较,如果大于给定距离,则将当前记录继续过滤掉,那么最终剩 下的数据结果集合,将是满足查询条件的地理位置结果集合。具体实现流程见如下代码:
//将笛卡尔层的Filter作为Geohash的Filter参数传递进去,形成一个过滤链
filter = distanceFilter = new GeoHashDistanceFilter(cartesianFilter, lat, lng, miles, geoHashFieldPrefix);
再看GeoHashDistanceFilter中最核心的方法getDocIdSet():
public DocIdSet getDocIdSet(IndexReader reader) throws IOException {
//在这里使用到了Lucene的FieldCache来作为缓存,实际上缓存了一个以docId为下标,base32编码为值的数组
final String[] geoHashValues = FieldCache.DEFAULT.getStrings(reader, geoHashField);
final int docBase = nextDocBase;
nextDocBase += reader.maxDoc();
return new FilteredDocIdSet(startingFilter.getDocIdSet(reader)) {
@Override
public boolean match(int doc) {
//通过笛卡尔层的过滤后的doc直接找到对应的base32编码
String geoHash = geoHashValues[doc];
//通过解码将base32还原成经纬度坐标
double[] coords = GeoHashUtils.decode(geoHash);
double x = coords[0];
double y = coords[1];
Double cachedDistance = distanceLookupCache.get(geoHash);
double d;
if (cachedDistance != null) {
d = cachedDistance.doubleValue();
} else {
//计算2个经纬度坐标的距离
d = DistanceUtils.getDistanceMi(lat, lng, x, y);
distanceLookupCache.put(geoHash, d);
}
//小于给定查询距离的的docid放入缓存,以供下次使用,同时返回True代表当前docId是满足条件的记录
if (d < distance){
distances.put(doc+docBase, d);
return true;
} else {
return false;
}
}
};
相关推荐
基于solr-geo空间搜索 1、Solr的schema.xml配置 定义坐标field 2、Solr的data-config.xml配置 建立索引 3、java查询语法 坐标距离、分页、排序
软件架构: MySQL+MyBatis+Spring+SpringMVC+Redis+Solr 项目描述:该商城是一个综合性的B2C平台,类似京东商城、天猫商城。用户可以在商城浏览商品、下订单,以及参加各种活动。该商城采用分布式系统架构,子系统...
##新闻搜索引擎我们从头开始构建了一个完整的信息检索系统,其中包括解析原始数据、将数据过滤到不同类别、创建索引、执行用户查询和计算相关性分数的模块。 该项目受到 Apache Solr 架构的启发,是 UB CSE535 信息...
《ElasticSearch:可扩展的开源弹性搜索解决方案》基于ElasticSearch 的0.2 版本,覆盖了ElasticSearch 各种功能和命令的应用,全面、详细地介绍了开源、分布式、RESTful,具有全文检索功能的搜索引擎ElasticSearch...
FlyCms 是一个类似知乎以问答为基础的完全开源的JAVA语言开发的社交网络建站程序,基于 Spring Boot+Bootstrap3+MyBatis+MYSQL+Solr+Ehcache 应用架构,专注于社区内容的整理、归类和检索,它集合了问答,digg,wiki...
java多商户配送系统源码法典联盟 Codice Alliance 是一个基于 DDF 的开源模块化集成框架,增加...索引和搜索空间意识 全文检索 XPath 搜索 XML 索引 开放地理空间联盟 (OGC) KML、CSW 和 WFS 联合服务 OpenSearch 联合
基本思想是将基于 VSM(向量空间模型)的工具集放在一起,用于可以从 VSM 提供的各种事物中获得一些帮助的各种事物。 对你来说够模糊吗? 我们从搜索/标记开始,但计划考虑更多。 此外,我们从一个简单的键/值存储...
3汤姆猫TomCat使用JAVA开发的TomCat,汤姆猫手机游戏,利用重绘实现4 Quark网络交流平台基于JSP实现的网络平台,实现了用户登录/注册功能,文章发表功能。。。 5 html实现拼图游戏利用html实现的网页版九宫格拼图...
AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...
AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...
AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...
AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...
AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...
AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...
AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...
AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...
AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...
AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...
AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...
AutoTips基于搜索引擎Apache Lucene实现。AutoTips提供统一UI。 WAP浏览器 j2wap j2wap 是一个基于Java的WAP浏览器,目前处于BETA测试阶段。它支持WAP 1.2规范,除了WTLS 和WBMP。 Java注册表操作类 jared jared是...