SolrCloud空间搜索测试

概述

空间查询是是利用点,线和多边形等地理信息获得满足特定空间关系的数据,广泛应用于新型农业、零售、服务和安全等领域。本文的业务背景也是基于活动轨迹的多边形查询。


一、空间搜索类型

Solr目前主要支持以下空间搜索类型:

  • 索引点或其他形状
  • 用边界框或圆形或其他形状过滤搜索结果
  • 通过点之间的距离或矩形之间的相对面积来排序或提升得分
  • 二维网格上生成热图或者点绘。

本次测试主要是针对多变形的intersect和within查询。

二、配置SOLR并导入测试数据

创建测试collection:geo_test, 步骤如下:

1. 配置schema

拷贝一份默认的schma配置SOLR_INSTALL/server/solr/configsets/_default到新目录geo_configs

在geo_configs目录下的managed-schema文件中增加新字段geo, 并修改location_rptfieldType

<!-- add field geo -->
<field name="geo" type="location_rpt" indexed="true" stored="true" multiValued="true" />

<!-- modify field type to support polygon -->
<fieldType name="location_rpt"   
   class="solr.SpatialRecursivePrefixTreeFieldType"
   spatialContextFactory="org.locationtech.spatial4j.context.jts.JtsSpatialContextFactory"
   autoIndex="true"
   validationRule="repairBuffer0"
   distErrPct="0.025"
   maxDistErr="0.001"
   distanceUnits="kilometers" />

为了支持doc id的自动生成,需要配置eo_configs目录下的solrconfig.xml文件。

<updateRequestProcessorChain>
 <processor class="solr.UUIDUpdateProcessorFactory"><str name="fieldName">id</str></processor>
 <processor class="solr.LogUpdateProcessorFactory" />
 <processor class="solr.RunUpdateProcessorFactory" />
</updateRequestProcessorChain>

2.创建schema

此处可以先上传conf到zk上,也可以直接通过solr命令中-d选项指定配置目录。

cd ${SOLR_HOME}
./server/scripts/cloud-scripts/zkcli.sh \
  -zkhost emr-header-1:2181 \
  -cmd upconfig \
  -confname geo_test \
  -confdir ../data/geo_configs/conf

bin/solr create -c geo_test -n geo_test -s 8

3.导入数据

使用curl导入所有的数据

# total 50k documents in this directory
cd geodata

for file in `ls small_data_*`
do
    echo "loading data file: $file.."
    curl  'http://localhost:8983/solr/geo_test/update/csv?commit=true&separator=%2C&fieldnames=geo,MSOA11NM_s,MSOA11CD_s&header=true' \
      -H 'Content-type:text/csv; charset=utf-8' \
      --data-binary @$file
    ((counter++))
done

通过访问http://spark:8983/solr/#/geo_test/query ,查看导入的数据。

四、测试

Solr Cloud环境

  • 共4个节点
  • 每个节点JVM MEMORY 4G

测试表:geo_test

  • 8个shard
  • 每个节点2个shard
  • 每个doc都的geo字段包含几百个顶点的多边形
  • 测试数据分别为10万、100万、2000万

通过Python脚本随机生成不同顶点个数的多边形,对Intersect和within的多边形查询进行测试。

#!/usr/bin/python
import random
import requests
import json

url = "http://localhost:8983/solr"
collection = 'geo_test'

def query(vertices_numbers, pattern, isPolygon = False):
    data=[ ]
    first_group = ''
    for i in range(vertices_numbers - 1):
        latitude = random.randint(-4677000, 4643800) / 100000
        longitude = random.uniform(-2470650, -2349470) / 100000
        group = "{}%20{}".format(latitude, longitude)
        data.append(group)
        if i == 0:
            first_group = group

    if vertices_numbers > 1 :
        data.append(first_group)

    query_data = ''
    if isPolygon:
        query_data ="POLYGON(({}))".format(",".join(data))
    else:
        query_data = " ".join(data)
    condition = "geo:%22{}({})%22&q=*:*".format(pattern, query_data)
    request = "{}/{}/select?fq={}".format(url, collection, condition)
    response = requests.get(request)
    json_data = json.loads(response.text)
    return "query time:{}(ms)".format(json_data['responseHeader']['QTime'])

def polygonIntersectsQuery(vertices_numbers):
    return "Polygon have:{} vertices. Polygon intersect {}".format(vertices_numbers, query(vertices_numbers, 'Intersects', True))

def polygonWithIn(vertices_numbers):
    return "Polygon have:{} vertices. Polyton within {}".format(vertices_numbers, query(vertices_numbers, 'WithIn', True))


if __name__ == '__main__':
    # polygon intersect query
    vertices_set = [10, 50, 100, 150, 200, 250]
    for v in vertices_set:
        print(polygonIntersectsQuery(v))

    # polygon within query
    for v in vertices_set:
        print(polygonWithIn(v))

五、结论

不同数据量、不同顶点多边形intersect的测试结果:

SolrCloud空间搜索测试

不同数据量、不同顶点多边形within的测试结果:

SolrCloud空间搜索测试

千万级别内的数据量,200-300个顶点的多边形复杂查询,毫秒级响应是没有问题的

参考

上一篇:当云HBase2.0被赋能了search


下一篇:[Phoenix] 九、分页查询