Solr Spatial Search
三种fieldType:
LatLonType
SpatialRecursivePrefixTreeFieldType(RPT)
BBoxField
Spatial Filters:
geofilt
&q=*:*&fq={!geofilt sfield=store}&pt=45.15,-93.85&d=5
all the results within the circle of the given radius around the initial point
bbox
&q=*:*&fq={!bbox sfield=store}&pt=45.15,-93.85&d=5
.
all the results in the box
specify large distErrPct value , the filter will run faster
arbitrary rectangle
RPT support
solr post filter
&q=...mykeywords...&fq=...someotherfilters...&fq={!geofilt cache=false cost=100}&sfield=store&pt=45.15,-93.85&d=5
distance function queries
geodist,dist,hsin,sqedist
geodist
sort result by distance asc
&q=*:*&fq={!geofilt}&sfield=store&pt=45.15,-93.85&d=50&sort=geodist asc
return distance as the document score
&q={!func}geodist()&sfield=store&pt=45.15,-93.85&sort=score+asc
More examples
use as a sub-query to expand the search results
Here we will query for results in Jacksonville, Florida, or within 50 kilometers of 45.15,-93.85 (near Buffalo, Minnesota):
&q=*:*&fq=(state:"FL" AND city:"Jacksonville") OR {!geofilt}&sfield=store&pt=45.15,-93.85&d=50&sort=geodist()+asc
facet by distance
To facet by distance, you can use the Frange query parser:
&q=*:*&sfield=store&pt=45.15,-93.85&facet.query={!frange l=0 u=5}geodist()&facet.query={!frange l=5.001 u=3000}geodist()
There are other ways to do it too, like using a {!geofilt} in each facet.query.
boost nearest results
&q.alt=*:*&fq={!geofilt}&sfield=store&pt=45.15,-93.85&d=50&bf=recip(geodist(),2,200,20)&sort=score desc
SpatialRecursivePrefixTreeFieldType (abbreviated as RPT)
Solr 4's new spatial field offers several new features and improvements over LatLonType:
- Query by polygons and other complex shapes, in addition to circles & rectangles
- Multi-valued indexed fields
- Ability to index non-point shapes (e.g. polygons) as well as point shapes
- Rectangles with user-specified corners that can cross the dateline
- Multi-value distance sort and score boosting (warning: non-optimized)
- Well-Known-Text (WKT) shape syntax (required for specifying polygons & other complex shapes)
RPT schema
class
distErrPct指中心点与边界距离的精确度,【0.0---0.5】越小越精确,索引慢,占用磁盘越多,查询慢,反之则反
geo 默认值为true,将应用经纬度坐标,数学模型是一个球体,false则是二维的xy坐标
maxDistErr 定义索引数据的详细程度,默认一米,只比0.000009 degrees小一点,这个设置用来在内部计算恰当的maxLevels
maxLevels 设置索引数据的最大格子深度,更直观的是通过指定maxDistErr来计算恰当的maxLevels
name
prefixTree 定义spatial grid的实现,prefixTree把一个地域范围映射成一个grid,每一个grid被分解成一系列下一级的sub grid ,如果geo=false默认的prefix tree是geohash,否则是quad,geohash有32个孩子grid,quad有4个。
spatialContextFactory 如果使用多边形,则需要指定它的实现(com.spatial4j.core.context.jts.JtsSpatialContextFactory),设置autoIndex=true提升多边形的性能
units 现在只能是degrees,是用来计算maxDistErr的,1degree大约111.2千米
worldBounds 如果geo=false则需要指定worldBounds,format : ENVELOPE(minX, maxX, maxY, minY)
samples
<
fieldType
name
=
"location_rpt"
class
=
"solr.SpatialRecursivePrefixTreeFieldType"
spatialContextFactory
=
"com.spatial4j.core.context.jts.JtsSpatialContextFactory"
autoIndex
=
"true"
distErrPct
=
"0.025"
maxDistErr
=
"0.000009"
units
=
"degrees"
/>
BBoxField
BBoxField索引一个矩形,支持通过boundary box 查询
samples
<
field
name
=
"bbox"
type
=
"bbox"
/>
<
fieldType
name
=
"bbox"
class
=
"solr.BBoxField"
geo
=
"true"
units
=
"degrees"
numberType
=
"_bbox_coord"
/>
<
fieldType
name
=
"_bbox_coord"
class
=
"solr.TrieDoubleField"
precisionStep
=
"8"
docValues
=
"true"
stored
=
"false"
/>
The latter is the only way to choose a predicate other than Intersects. For example:
&q={!field f=bbox}Contains(ENVELOPE(-10, 20, 15, 10))
Now to sort the results by one of the relevancy modes, use it like this:
&q={!field f=bbox score=overlapRatio}Intersects(ENVELOPE(-10, 20, 15, 10))
You can also use&debug=results
to see useful score computation info.