根据坐标搜索,在这里叫空间搜索,又名Spatial Search(Spatial Query),这个技术是很复杂还有复杂的算法什么的,都不关注了,能用就行吧,主要是实现根据gps坐标搜索出最近的门店,我用的是百度坐标,貌似什么坐标都可以距离算的还是比较准确的。
一、创建核心与配置
solr create -c jts -force 创建一个jts的核心
managed-schema 配置
<uniqueKey>id</uniqueKey>
<field name="id" type="string" multiValued="false" indexed="true" required="true" stored="true"/>
<field name="lat" type="string" indexed="true" stored="true"/>
<field name="lng" type="string" indexed="true" stored="true"/>
<field name="position" type="location_rpt" indexed="true" stored="true"/>
<field name="shop_name" type="string" indexed="true" stored="true"/>
<field name="address" type="string" indexed="true" stored="true"/>
二、Java相关代码片段
Shop.java 实体类
import lombok.Data;
import org.apache.solr.client.solrj.beans.Field;
/**
* 门店信息
*/
@Data
public class Shop {
@Field()
private String id;
@Field("shop_name")
private String shopName;
@Field
private String address;
@Field
private String lng; //经度
@Field
private String lat; //纬度
@Field
private String position; // 经度 + 维度
@Field
private float distance;//距离(用于查询计算后返回时使用)
public Shop() {
}
public Shop(Integer id, String shopName, String address, String lng, String lat) {
this.id = id + "";
this.shopName = shopName;
this.address = address;
this.lng = lng;
this.lat = lat;
this.position = lat + "," + lng;
}
}
实现类写入门店信息,使用的是SolrTemplate
@Override
public UpdateResponse addShopInfo() {
List<Shop> list = new ArrayList<>();
list.add(new Shop(4, "北京-朝外店", "北京市朝阳区朝外sohoD座5110", "116.460557", "39.932558"));
list.add(new Shop(6, "北京-人大店", "北京市海淀区北三环西路47号院乙10-6号", "116.320896", "39.97292"));
list.add(new Shop(11, "北京-顺义店", "北京市顺义区西辛南区55号楼南侧西辛南区市场106号", "116.649471", "40.14375"));
list.add(new Shop(12, "北京-通州店", "北京市通州区梨园镇孙王场村委会北100米永盛超市底商", "116.666536", "39.895731"));
list.add(new Shop(13, "北京-霍营店", "北京市昌平区农业部干部管理学院东门", "116.374155", "40.087722"));
list.add(new Shop(15, "北京-大兴店", "北京市大兴区黄村镇清源路甲1号2幢1层5号", "116.351174", "39.751916"));
list.add(new Shop(16, "北京-方庄店", "北京市朝阳区成寿寺路134号院中海城紫鑫阁", "116.454459", "39.855097"));
list.add(new Shop(17, "北京-六里桥店", "北京市丰台区六里桥西三环中路太平27号楼底商", "116.318273", "39.897132"));
list.add(new Shop(18, "北京-洋桥店", "北京市角门东里12号楼西侧底商117号维尔纳斯", "116.391781", "39.856717"));
list.add(new Shop(19, "北京-安贞店", "北京市黄寺大街15号佰隆大厦4层423", "116.397372", "39.980888"));
list.add(new Shop(23, "北京-昌平南口店", "昌平区南口镇兴隆街麦利宝手感烘焙", "116.134199", "40.244248"));
list.add(new Shop(34, "北京-石景山店", "石景山区古盛路36号院(中海金鑫阁)3号楼3019号", "116.189029", "39.929496"));
list.add(new Shop(37, "北京-上地店", "安宁庄西路9号院25号楼1层112(imoma大厦底商,佳汇儿园对面)", "116.321404", "40.057441"));
list.add(new Shop(42, "北京-亦庄店", "天华北街5号院一层西侧103维尔纳斯", "116.504375", "39.817262"));
list.add(new Shop(48, "北京-石佛营店", "北京市朝阳区卜蜂莲花超市(石佛营店)内", "116.508188", "39.937419"));
list.add(new Shop(53, "北京-昌平店", "昌平区鼓楼南大街38~4", "116.239485", "40.222828"));
list.add(new Shop(96, "北京-沙河店", "沙河镇松兰堡村西海林自控院内一楼148室", "116.293338", "40.161073"));
list.add(new Shop(108, "北京-房山店", "北京市房山区阜盛东街57号院4号楼1层105", "116.198006", "39.746316"));
list.add(new Shop(122, "北京-来广营店", "朝阳区来广营 铁建广场 D座1层105室", "116.44598", "40.053336"));
list.add(new Shop(159, "北京-顺义2店", "北京市顺义区顺仁路66号院2号楼B112底商", "116.672922", "40.091715"));
UpdateResponse updateResponse = solrTemplate.saveBeans("jts", list);
solrTemplate.commit("jts");
return updateResponse;
}
根据坐标查询 这里使用了Solrj 查询,SolrTemplate 查询条件不知道怎么去设置,感觉 太返人类,使用控制台查询条件也不知道怎么输入
@Override
public List<Shop> getByGps(String gps) {
SolrQuery query = new SolrQuery();
query.set("q", "*:*");
query.set("fq", "{!geofilt}"); //距离过滤器
query.set("d", "10"); //距离 单位公里
query.set("pt", gps); //参考点坐标 "39.939549858674226,116.82007871201711" [纬度,经度]
query.set("sfield", "position"); //坐标字段
query.set("start", "0"); //起始记录
query.set("rows", "10"); //分页
query.set("sort", "geodist() asc"); //排序规则
query.set("fl", "*,distance:geodist()");//返回的距离 5.834996E-5 注意这个科学计数法坑爹的很,单位是千米,实际是0.0000xxx使用了科学技术法
//执行查询并且返回结果
QueryResponse reponse = null;
try {
reponse = solrClient.query("jts", query);
//获取匹配返回的结果
SolrDocumentList list = reponse.getResults();
for (SolrDocument doc : list)
System.out.println(doc);
//匹配结果总数
long count = list.getNumFound();
System.out.println("匹配结果总数:" + count);
return reponse.getBeans(Shop.class);
} catch (SolrServerException | IOException e) {
e.printStackTrace();
}
return null;
}
这是查询10公里之内的并且按距离排序的数据