lucene geohash 在外卖场景中,商家不规则多边形配送范围技术应用

一、场景描述   

   当我们在定外卖的时候,系统是如何根据我们的位置搜到附近商家,当商家的配送范围是不规则的时候,系统是如何处理。

 二、 理论基础

1. GeoHash特点
1)GeoHash用一个字符串表示经度和纬度两个坐标,比如我现在所在位置的GeoHash值为 wx4sv61q;
2)GeoHash标识的并不是一个点,而是一个区域,比如 wx4sv61q 对应的就是一个矩形区域;
3)编码的前缀可以标识更大的区域,比如 wx4sv61 编码代表的区域要大于 wx4sv61q 代表的区域,但是 wx4sv61q 代表的区域一定在 wx4sv61 代表的区域内。
      因此我们再去做距离检索的时候,只需要对GeoHash进行前缀匹配即可

2.GeoHash原理

  GeoHash最简单的解释就是将一个位置信息转化成一个可以排序、可以比较的字符串编码

      具体的实现大家可以自行百度

  3.如何证明点在面里      

A.夹角和判别法:判断目标点与所有边的夹角和是否为360度,为360度则在多边形内部。

B.引射线法:从目标点出发引一条射线,看这条射线和多边形所有边的交点数目。如果有奇数个交点,则说明在内部,如果有偶数个交点,则说明在外部。

具体做法:将测试点的Y坐标与多边形的每一个点进行比较,会得到一个测试点所在的行与多边形边的交点的列表。在下图的这个例子中有8条边与测试点所在的行相交,而有6条边没有相交。如果测试点的两边点的个数都是奇数个则该测试点在多边形内,否则在多边形外。在这个例子中测试点的左边有5个交点,右边有三个交点,它们都是奇数,所以点在多边形内。

                                   lucene geohash 在外卖场景中,商家不规则多边形配送范围技术应用_第1张图片

C.  java.awt.geom.GeneralPath  jdk自带画图工具,相对来说比较简单

三、实习方式

       1.用  lucene GeoHash 在索引中 统计出用户  10公里范围内的商家

        2. 计算此用户是否在每个商家的配送范围内。(证明二维空间里  点是否面里)

四、代码实现

pom.xml  所需的maven依赖配置

  
    UTF-8
    6.1.0
  

  
    
      com.fasterxml.jackson.core
      jackson-databind
      2.8.1
    
    
      org.apache.lucene
      lucene-core
      ${lib.lucene.version}
    
    
      org.apache.lucene
      lucene-analyzers-common
      ${lib.lucene.version}
    
    
      org.apache.lucene
      lucene-spatial
      ${lib.lucene.version}
    
    
      org.apache.lucene
      lucene-spatial-extras
      ${lib.lucene.version}
    
    
      org.apache.lucene
      lucene-analyzers-smartcn
      ${lib.lucene.version}
    
    
      org.apache.zookeeper
      zookeeper
      3.4.9
    


    
      redis.clients
      jedis
      2.8.0
    




    
      org.junit.jupiter
      junit-jupiter-api
      5.0.2
    

    
      commons-lang
      commons-lang
      2.6
    

    
      commons-io
      commons-io
      2.5
    


    
      org.apache.curator
      curator-framework
      4.0.0
    

    
      org.apache.curator
      curator-client
      4.0.0
      
        
          slf4j-api
          org.slf4j
        
        
          zookeeper
          org.apache.zookeeper
        
      
    
    
      org.apache.curator
      curator-recipes
      4.0.0
    


    
      com.alibaba
      fastjson
      1.2.6
    


    
      com.101tec
      zkclient
      0.10
      
        
          zookeeper
          org.apache.zookeeper
        
      
    

    
      junit
      junit
      3.8.1
      test
    

    
      com.fasterxml.jackson.core
      jackson-databind
      2.5.3
    

    
      org.codehaus.jackson
      jackson-core-asl
      1.9.13
    

  

代码实现

package com.people.lucene;

/**
 * Created by Administrator on 2018/1/4.
 */
import java.awt.geom.Point2D;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.NumericDocValuesField;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.spatial.SpatialStrategy;
import org.apache.lucene.spatial.prefix.RecursivePrefixTreeStrategy;
import org.apache.lucene.spatial.prefix.tree.GeohashPrefixTree;
import org.apache.lucene.spatial.prefix.tree.SpatialPrefixTree;
import org.apache.lucene.spatial.query.SpatialArgs;
import org.apache.lucene.spatial.query.SpatialOperation;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;

import org.locationtech.spatial4j.context.SpatialContext;
import org.locationtech.spatial4j.distance.DistanceUtils;
import org.locationtech.spatial4j.shape.Point;
import org.locationtech.spatial4j.shape.Shape;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * Lucene spatial演示
 *
 */
public class SpatialExample {


    public static void main(String[] args) {
        init();
        try {
            indexPoints();
            search();
        }catch (Exception e){
            e.printStackTrace();
        }

    }
    public void test() throws Exception {

    }

    /** Spatial4j上下文 */
    private static SpatialContext ctx;// "ctx" is the conventional variable name

    /** 提供索引和查询模型的策略接口 */
    private static SpatialStrategy strategy;

    /** 索引目录 */
    private static Directory directory;

    private static void init() {
        // SpatialContext也可以通过SpatialContextFactory工厂类来构建
        ctx = SpatialContext.GEO;

        //网格最大11层, geohash的精度
        int maxLevels = 11;

        //Spatial Tiers
        SpatialPrefixTree grid = new GeohashPrefixTree(ctx, maxLevels);

        strategy = new RecursivePrefixTreeStrategy(grid, "myGeoField");

        directory = new RAMDirectory();
    }

      public  static void indexPoints() throws Exception {
        IndexWriterConfig iwConfig = new IndexWriterConfig(new SmartChineseAnalyzer());
        IndexWriter indexWriter = new IndexWriter(directory, iwConfig);

        JsonFactory jsonFactory = new JsonFactory();
        jsonFactory.enable(JsonParser.Feature.ALLOW_COMMENTS);
        ObjectMapper mapper = new ObjectMapper(jsonFactory);

        BufferedReader br = new BufferedReader(new InputStreamReader(
                SpatialExample.class.getClassLoader().getResourceAsStream("shop.json")));

        String line = null;
        while ((line = br.readLine()) != null) {
            ShopBean shopBean = mapper.readValue(line, ShopBean.class);
            //这里的x,y即经纬度,x为Longitude(经度),y为Latitude(纬度)
            Document document = newSampleDocument(shopBean.getId(), shopBean.getName(),shopBean.getShape() ,ctx.makePoint(shopBean.getLongitude(), shopBean.getLatitude()));
            indexWriter.addDocument(document);
        }

        indexWriter.close();
    }

    private static Document newSampleDocument(int id, String title, String shapeEnclosure ,Shape... shapes) {
        Document doc = new Document();
        doc.add(new StoredField("id", id));
        doc.add(new NumericDocValuesField("id", id));
        doc.add(new TextField("name", title, Store.YES));
        doc.add(new TextField("shape", shapeEnclosure, Store.YES));


        // Potentially more than one shape in this field is supported by some
        // strategies; see the javadocs of the SpatialStrategy impl to see.
        for (Shape shape : shapes) {
            for (Field f : strategy.createIndexableFields(shape)) {
                doc.add(f);
            }
            // store it too; the format is up to you
            // (assume point in this example)
            Point pt = (Point) shape;
            doc.add(new StoredField(strategy.getFieldName(), pt.getX() + " " + pt.getY()));
        }

        return doc;
    }

    public static void search() throws Exception {
        searchInner("密室");
        System.out.println("----------------");
        //searchInner("咖啡");
    }

    private  static void searchInner(String keyword) throws Exception {
        IndexReader indexReader = DirectoryReader.open(directory);
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);

        // --Filter by circle (<= distance from a point)
        // Search with circle
        // note: SpatialArgs can be parsed from a string
        //Point pt = ctx.makePoint(121.41791, 31.21867);
        Point pt = ctx.makePoint(116.45845, 39.983086);
        // the distance in km
        ValueSource valueSource = strategy.makeDistanceValueSource(pt, DistanceUtils.DEG_TO_KM);
        //按距离由近及远排序
        Sort distSort = new Sort(valueSource.getSortField(false)).rewrite(indexSearcher); // false=asc                                                                                         dist

        SpatialArgs args = new SpatialArgs(SpatialOperation.Intersects,
                ctx.makeCircle(pt, DistanceUtils.dist2Degrees(3.0, DistanceUtils.EARTH_MEAN_RADIUS_KM)));
        Query query = strategy.makeQuery(args);

        BooleanQuery.Builder bqb = new BooleanQuery.Builder();
        bqb.add(query, BooleanClause.Occur.MUST);
        bqb.add(new TermQuery(new Term("name", keyword)), BooleanClause.Occur.MUST);

        TopDocs docs = indexSearcher.search(bqb.build(), 20, distSort);
        printDocs(indexSearcher, docs, args);

        indexReader.close();
    }

    private static void printDocs(IndexSearcher indexSearcher, TopDocs docs, SpatialArgs args) throws IOException {
        for (int i = 0; i < docs.totalHits; i++) {
            Document doc = indexSearcher.doc(docs.scoreDocs[i].doc);

            //判断是否在商家配送范围内
            if(null !=doc.getField("shape").stringValue()){
                PageData orderLocation = new PageData();
                orderLocation.setX( "116.45845");
                orderLocation.setY( "39.983086");
                // 商业区域(百度多边形区域经纬度集合)
                 boolean isInclude = isInPolygon(orderLocation, doc.getField("shape").stringValue());
                //如果不在范围内,不做展示
                if(!isInclude){
                    continue;
                }

            }






            System.out.print(doc.getField("id").numericValue().intValue());
            System.out.print(":" + doc.getField("name").stringValue());

            //计算距离
            String docStr = doc.getField(strategy.getFieldName()).stringValue();
            // assume docStr is "x y" as written in newSampleDocument()
            int spaceIdx = docStr.indexOf(' ');
            double x = Double.parseDouble(docStr.substring(0, spaceIdx));
            double y = Double.parseDouble(docStr.substring(spaceIdx + 1));
            double docDistDEG = ctx.calcDistance(args.getShape().getCenter(), x, y);

            System.out.print("(" + DistanceUtils.degrees2Dist(docDistDEG, DistanceUtils.EARTH_MEAN_RADIUS_KM) + "km)");

            System.out.println();
        }
    }









    /**
     * 判断当前位置是否在多边形区域内
     * @param orderLocation 当前点
     * @param partitionLocation 区域顶点
     * @return
     */
    public static boolean isInPolygon(PageData orderLocation,String partitionLocation){

        double p_x =Double.parseDouble(orderLocation.getX());
        double p_y =Double.parseDouble(orderLocation.getY());
        Point2D.Double point = new Point2D.Double(p_x, p_y);

        List pointList= new ArrayList();
        String[] strList = partitionLocation.split(",");

        for (String str : strList){
            String[] points = str.split("_");
            double polygonPoint_x=Double.parseDouble(points[1]);
            double polygonPoint_y=Double.parseDouble(points[0]);
            Point2D.Double polygonPoint = new Point2D.Double(polygonPoint_x,polygonPoint_y);
            pointList.add(polygonPoint);
        }
        //return IsPtInPoly(point,pointList);    //   true
        return checkWithJdkGeneralPath(point,pointList);  // true

    }
    /**
     * 返回一个点是否在一个多边形区域内, 如果点位于多边形的顶点或边上,不算做点在多边形内,返回false
     * @param point
     * @param polygon
     * @return
     */
    public static boolean checkWithJdkGeneralPath(Point2D.Double point, List polygon) {
        java.awt.geom.GeneralPath p = new java.awt.geom.GeneralPath();
        Point2D.Double first = polygon.get(0);
        p.moveTo(first.x, first.y);
        polygon.remove(0);
        for (Point2D.Double d : polygon) {
            p.lineTo(d.x, d.y);
        }
        p.lineTo(first.x, first.y);
        p.closePath();

        return p.contains(point);
    }





    /**
     * 判断点是否在多边形内,如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
     * @param point 检测点
     * @param pts   多边形的顶点
     * @return      点在多边形内返回true,否则返回false
     */
    public static boolean IsPtInPoly(Point2D.Double point, List pts){

        int N = pts.size();
        boolean boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
        int intersectCount = 0;//cross points count of x
        double precision = 2e-10; //浮点类型计算时候与0比较时候的容差
        Point2D.Double p1, p2;//neighbour bound vertices
        Point2D.Double p = point; //当前点

        p1 = pts.get(0);//left vertex
        for(int i = 1; i <= N; ++i){//check all rays
            if(p.equals(p1)){
                return boundOrVertex;//p is an vertex
            }

            p2 = pts.get(i % N);//right vertex
            if(p.x < Math.min(p1.x, p2.x) || p.x > Math.max(p1.x, p2.x)){//ray is outside of our interests
                p1 = p2;
                continue;//next ray left point
            }

            if(p.x > Math.min(p1.x, p2.x) && p.x < Math.max(p1.x, p2.x)){//ray is crossing over by the algorithm (common part of)
                if(p.y <= Math.max(p1.y, p2.y)){//x is before of ray
                    if(p1.x == p2.x && p.y >= Math.min(p1.y, p2.y)){//overlies on a horizontal ray
                        return boundOrVertex;
                    }

                    if(p1.y == p2.y){//ray is vertical
                        if(p1.y == p.y){//overlies on a vertical ray
                            return boundOrVertex;
                        }else{//before ray
                            ++intersectCount;
                        }
                    }else{//cross point on the left side
                        double xinters = (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y;//cross point of y
                        if(Math.abs(p.y - xinters) < precision){//overlies on a ray
                            return boundOrVertex;
                        }

                        if(p.y < xinters){//before ray
                            ++intersectCount;
                        }
                    }
                }
            }else{//special case when ray is crossing through the vertex
                if(p.x == p2.x && p.y <= p2.y){//p crossing over p2
                    Point2D.Double p3 = pts.get((i+1) % N); //next vertex
                    if(p.x >= Math.min(p1.x, p3.x) && p.x <= Math.max(p1.x, p3.x)){//p.x lies between p1.x & p3.x
                        ++intersectCount;
                    }else{
                        intersectCount += 2;
                    }
                }
            }
            p1 = p2;//next ray left point
        }

        if(intersectCount % 2 == 0){//偶数在多边形外
            return false;
        } else { //奇数在多边形内
            return true;
        }
    }

    static class  PageData {

        private String X ;
        private String Y ;

        public String getX() {
            return X;
        }

        public void setX(String x) {
            X = x;
        }

        public String getY() {
            return Y;
        }

        public void setY(String y) {
            Y = y;
        }
    }




}
ShopBean  实体类
package com.people.lucene;

/**
 * Created by Administrator on 2018/1/4.
 */
public class ShopBean {
    private int id;
    private String name;
    private double longitude;
    private double latitude;
    private String address;
    private String shape;

    public String getShape() {
        return shape;
    }

    public void setShape(String shape) {
        this.shape = shape;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getLongitude() {
        return longitude;
    }

    public void setLongitude(double longitude) {
        this.longitude = longitude;
    }

    public double getLatitude() {
        return latitude;
    }

    public void setLatitude(double latitude) {
        this.latitude = latitude;
    }
}
shop.jon 数据
 
  
{"id":22130906,"name":"小仙屋剧情密室逃脱","address":"浙江南路78号东新大厦216室","longitude":116.45845,"latitude":39.983086,"shape":"39.985962_116.456579,39.983032_116.452663,39.980931_116.453345,39.979853_116.45604,39.979632_116.462005,39.985023_116.465095"}
{"id":22130905,"name":"nook诺克密室&DIY多肉(人民广场店)","address":"浙江南路78号东新大厦216室","longitude":121.48206,"latitude":31.2288,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":2871847,"name":"星巴克(江苏店)","address":"江苏路458号1层116","longitude":121.43091,"latitude":31.218975,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":18179096,"name":"极道真人密室逃脱(人民广场大世界总店)","address":"金陵东路569号汇通大厦804室","longitude":121.48103,"latitude":31.226982,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":22676436,"name":"I high club","address":"上大路99号","longitude":121.39542,"latitude":31.312284,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":16820366,"name":"小仙屋剧情密室逃脱","address":"胶州路941号长久商务中心2203室","longitude":121.436646,"latitude":31.237585,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":8852374,"name":"魔方剧情真人密室逃脱(静安店)","address":"西康路618号华通大厦13楼D座","longitude":121.446335,"latitude":31.23506,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":24065790,"name":"A9真人密室逃脱(黄浦店)","address":"福州路465号上海书城6楼贝亦迪科技体验馆","longitude":121.48146,"latitude":31.23335,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":66552930,"name":"Charles' VR 虚拟现实体验馆","address":"五角场大学路161号701室","longitude":121.509865,"latitude":31.304022,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":8843152,"name":"iDream真人密室逃脱(百米香榭店)","address":"浙江路229号百米香榭街354店铺","longitude":121.479,"latitude":31.233591,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":11579304,"name":"1617Cafe(中山公园龙之梦服务区)","address":"长宁路890号玫瑰坊1楼88B","longitude":121.41786,"latitude":31.219374,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":19649586,"name":"MC精品真人密室逃脱(八佰伴店)","address":"浦东南路1088号4F-05","longitude":121.515366,"latitude":31.228285,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":66350697,"name":"初鱼vr咖-虚拟现实体验馆","address":"大学路103号802室","longitude":121.51079,"latitude":31.304335,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":3564328,"name":"Boom Cafe","address":"宣化路313号","longitude":121.42288,"latitude":31.216875,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":6850935,"name":"nook诺克密室逃脱(长宁店)","address":"中山公园附近","longitude":121.4217,"latitude":31.215496,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":23306435,"name":"暗黑魔盒集中营(鬼屋密室)","address":"翔殷路1099号4楼","longitude":121.51839,"latitude":31.30048,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":6438722,"name":"Min魔魔岛密室逃脱(中山公园店)","address":"长宁路988号花园大厦6楼606室","longitude":121.417885,"latitude":31.21871,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":5411446,"name":"COSTA COFFEE(上海长宁新世界)","address":"长宁路823号1楼","longitude":121.42047,"latitude":31.21866,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":7658577,"name":"因奥密室","address":"锦秋路699弄二区一排121号","longitude":121.38976,"latitude":31.32106,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":17163949,"name":"aMaze真人密室逃脱","address":"长宁路988号花园大厦903","longitude":121.41791,"latitude":31.21867,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":21930982,"name":"MANGOSIX(长宁龙之梦店)","address":"长宁路1018号龙之梦购物中心1楼1075号铺","longitude":121.41745,"latitude":31.21966,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":13915001,"name":"ZOOCOFFEE(定西路店)","address":"定西路1100号辽油大厦101室","longitude":121.42346,"latitude":31.2117,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":8019669,"name":"贝克街5号密室逃脱","address":"长寿路181弄日月星辰2号楼1007室","longitude":121.4421,"latitude":31.241724,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":67979580,"name":"Zero VR零维虚拟现实体验馆","address":"定西路1310弄18号303","longitude":121.42359,"latitude":31.215818,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":21374196,"name":"Dobe密室逃脱(杨浦大学路店)","address":"大学路33号701室loft37运动酒吧楼上","longitude":121.5117,"latitude":31.3047,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":17999648,"name":"DTR梦空间密室逃脱(八佰伴店)","address":"张杨路628弄东明广场2号楼2203室","longitude":121.52058,"latitude":31.228123,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":22636011,"name":"猫小姐的店","address":"长宁路890号玫瑰坊1楼","longitude":121.41781,"latitude":31.219257,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":23516373,"name":"Forest Rose Afternoon Tea","address":"长宁路890号玫瑰坊1F-72","longitude":121.418724,"latitude":31.21922,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":23550163,"name":"白兔子密室逃脱","address":"长宁路405弄1号地下1层","longitude":121.427055,"latitude":31.22307,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":32392280,"name":"海盗奇兵密室逃脱(五角场店)","address":"大学路33号601室loft37运动酒吧楼上","longitude":121.511765,"latitude":31.304789,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":56588006,"name":"第五空间咖啡馆","address":"长宁路1018号龙之梦购物中心4楼4202","longitude":121.41633,"latitude":31.218613,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":32508745,"name":"Vital Tea(长宁龙之梦店)","address":"长宁路1018号龙之梦购物中心1F-1055","longitude":121.41703,"latitude":31.21874,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":58805309,"name":"探险者世界(VR体验馆)","address":"人民广场迪美购物中心B1层","longitude":121.47345,"latitude":31.228691,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":57380950,"name":"阿拉丁真人密室逃脱(八佰伴店)","address":"张杨路628弄东明广场3号2C","longitude":121.52024,"latitude":31.22793,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":17950766,"name":"JOJO真人密室逃脱","address":"长寿路457号2楼C室","longitude":121.43657,"latitude":31.23879,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":57832242,"name":"Daisy花&咖啡","address":"江苏路54弄18号后门","longitude":121.42814,"latitude":31.223377,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":28615799,"name":"Let it go台球密室逃脱","address":"国济路20号七楼","longitude":121.51599,"latitude":31.30196,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":38092929,"name":"趣密室 & DIY手工坊","address":"石门二路333弄3号振安广场恒安大厦22楼E座","longitude":121.4598,"latitude":31.235432,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":57546152,"name":"好久不读 long time no read","address":"愚园路1208号","longitude":121.42646,"latitude":31.219221,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":66865461,"name":"VR family-虚拟现实体验馆","address":"大学路锦创路20号1101室创智66商务楼内(一兆韦德健身馆旁)","longitude":121.50922,"latitude":31.304209,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":9335488,"name":"77密室逃脱+真人CS(五角场店)","address":"四平路2500号东方商厦楼上金岛大厦1305室","longitude":121.515465,"latitude":31.298822,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":23062800,"name":"毛利侦探事务所密室逃脱","address":"大学路302号702室","longitude":121.50763,"latitude":31.30317,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":50431953,"name":"颠九宫真人游戏体验馆(杨浦店)","address":"国权路与邯郸路交叉口","longitude":121.50096,"latitude":31.297478,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":14155399,"name":"慢时光MYTIMECAFE","address":"武夷路339号","longitude":121.42406,"latitude":31.21347,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":59180246,"name":"月球剧情密室逃脱(淮海中路店)","address":"普安路189号曙光大厦18D","longitude":121.47889,"latitude":31.22244,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":27174604,"name":"MC精品真人密室逃脱(五角场店)","address":"翔殷路1128号8楼B4、B5","longitude":121.51691,"latitude":31.30103,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":32640417,"name":"西塞密室(长宁店)","address":"愚园路1391号3楼","longitude":121.42288,"latitude":31.218843,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":23403568,"name":"暗黑迷宫第三季","address":"南京西路1788号1788广场F201","longitude":121.44376,"latitude":31.22278,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":7045554,"name":"巴黎春天新世界酒店浓咖啡","address":"定西路1555号酒店2楼","longitude":121.4211,"latitude":31.218554,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":24899623,"name":"GIVE ME FIVE剧情密室逃脱(大学路店)","address":"大学路锦创路26号1102室创智66商务楼内","longitude":121.50918,"latitude":31.30425,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":67335522,"name":"nook诺克剧情密室 & VR虚拟现实体验馆(五角场店)","address":"大学路锦创路26号1602室创智66商务楼内","longitude":121.509315,"latitude":31.304174,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":4275877,"name":"Home Garden","address":"安化路492号德必易园多媒体创意园区106室","longitude":121.4202,"latitude":31.215342,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":18593150,"name":"TIK  TOK","address":"江苏路458号112室舜元企业发展大厦","longitude":121.43106,"latitude":31.218548,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":22447664,"name":"Running基地","address":"军工路100号","longitude":121.558266,"latitude":31.281694,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":24678174,"name":"太平洋咖啡(兆丰广场店)","address":"长宁路999号兆丰广场","longitude":121.41788,"latitude":31.21765,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":57439748,"name":"essence casa","address":"愚园路1329号","longitude":121.42449,"latitude":31.21873,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":65835399,"name":"大华虎城第三空间","address":"白丽路61号","longitude":121.35216,"latitude":31.27899,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":19671618,"name":"FullHouse桌游棋牌密室(南京西路店)","address":"大田路129号嘉发大厦A座25楼G","longitude":121.46391,"latitude":31.23294,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":23740568,"name":"aMaze真人密室逃脱(人民广场大世界店)","address":"云南南路180号淮云大厦8楼","longitude":121.48128,"latitude":31.2265,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":22132387,"name":"智源咖啡(中山公园店)","address":"安化路492号易园","longitude":121.42034,"latitude":31.21529,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":56890263,"name":"跑男开始了 runningman(公司活动,年会撕名牌)","address":"淮海中路","longitude":121.49525,"latitude":31.22792,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":18636516,"name":"ASA亚撒真人密室逃脱","address":"武夷路418弄(近定西路)1号武定大厦203室","longitude":121.421974,"latitude":31.212627,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":5857955,"name":"Crazycube颠九宫密室逃脱(大学路店)","address":"创智坊大学路302号701室","longitude":121.50754,"latitude":31.303108,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":2036581,"name":"星巴克(龙之梦2店)","address":"长宁路1018号龙之梦购物中心1楼1073号铺","longitude":121.416916,"latitude":31.218727,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":13913129,"name":"Captain.C真人密室逃脱","address":"延平路69号延平大厦701室","longitude":121.44161,"latitude":31.227833,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}
{"id":57682702,"name":"aMaze真人密室逃脱(五角场店)","address":"大学路292号602室","longitude":121.50777,"latitude":31.30327,"shape":"31.839064_117.219116,31.83253_117.219403,31.828511_117.218146,31.826763_117.219259,31.826118_117.220517,31.822713_117.23586,31.822958_117.238375,31.838512_117.23798,31.839617_117.226194,31.839586_117.222925"}


 
  




  


你可能感兴趣的:(lucene,spatial,SolrCloud,lucene,lucene,geohash,如何证明点在面里,spatial,LBS之外卖场景)