spring mongodb geo 位置搜索服务 示例

1、项目关联jar文件


2、配置mongodb.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mongo="http://www.springframework.org/schema/data/mongo"
	xsi:schemaLocation="http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/data/mongo http://www.springframework.org/schema/data/mongo/spring-mongo-1.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
	<!-- Default bean name is 'mongo' -->
	<mongo:mongo host="192.168.1.88" port="27017" />
	<mongo:db-factory dbname="database" mongo-ref="mongo" />
	
	<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
		<constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />		
	</bean>
	
	<bean id="businessDao" class="com.spring.operation.BusinessDao"></bean>
	<bean id="businessPositionDao" class="com.spring.operation.BusinessPositionDao"></bean>
	<bean id="mongoDaoImpl" class="com.spring.operation.MongoDaoImpl"></bean>
</beans>

3、mongodb 父接口类

<span style="font-size:12px;">package com.spring.mongodb;

import java.util.List;
import com.mongodb.DBObject;  
  
/** 
 * mongodb 父接口类 
 * @author zhouzhigang 
 * @version 1.1 
 * @date 2016年11月09日-下午1:42:23 
 */  
public interface  MongoDao {  
      
    public DBObject findOne(String collection, DBObject query, DBObject fields);  
       
    public List<DBObject> find(String collection, DBObject query, DBObject fields, DBObject orderBy, int pageNum, int pageSize);  
   
    public List<DBObject> find(String collection, DBObject query, DBObject fields, DBObject orderBy, int limit);  
   
    public void delete(String collection, DBObject dbObject);  
   
    public void save(String collection, DBObject dbObject);  
   
    public void update(String collection, DBObject query, DBObject update, boolean upsert, boolean multi);  
   
    public Long count(String collection, DBObject query);  
   
    public List<?> distinct(String collection, String key, DBObject query);  
   
}  </span>


4、Mondodb 地址运算 接口类

<span style="font-size:12px;">package com.spring.mongodb;


import com.mongodb.DBObject;  
import com.spring.entity.Point;
import java.util.List;  
/**
 * Mondodb 地址运算 接口类
 * 
 * @author zhouzhigang
 * @version 1.1
 * @date 2016年11月09日-下午1:50:06
 */
public interface MongoGeoDao extends MongoDao {
	/**
	 * 聚合查询,查询一个点附近的点,并返回每一个点到该中心点的距离,在坐标表分片的情况下$nearSphere不支持, 可以使用该方法进行查询
	 * 
	 * @param collection
	 *            集合名称
	 * @param query
	 *            查询条件
	 * @param point
	 *            中心点坐标
	 * @param limit
	 *            返回记录数量限制
	 * @param maxDistance
	 *            最大距离
	 * @return 非NULL的list
	 */
	public List<DBObject> geoNear(String collection, DBObject query,
			Point point, int limit, long maxDistance);

	/**
	 * 查询在圆形区域内的坐标点,需要指定中心点坐标和半径,半径单位是米
	 * 
	 * @param collection
	 *            集合名称
	 * @param locationField
	 *            坐标字段
	 * @param center
	 *            中心点坐标[经度,纬度]
	 * @param radius
	 *            半径 单位:米
	 * @param fields
	 *            查询字段
	 * @param query
	 *            查询条件
	 * @param limit
	 *            返回记录限制数量
	 * @return 非NULL的list
	 */
	public List<DBObject> withinCircle(String collection, String locationField,
			Point center, long radius, DBObject fields, DBObject query,
			int limit);

	/**
	 * 指定一个点,返回该点附近的坐标点且是由近到远,$nearSphere 需要建立索引2dsphere 或者2d,并且支持GeoJSON和一般坐标对
	 * 注意: $nearSphere在分片的集群中无效,使用geoNear
	 * 
	 * @param collection
	 *            集合名称
	 * @param locationField
	 *            坐标字段
	 * @param center
	 *            中心点坐标[经度,纬度]
	 * @param minDistance
	 *            最近距离
	 * @param maxDistance
	 *            最远距离
	 * @param query
	 *            查询条件
	 * @param fields
	 *            查询字段
	 * @param limit
	 *            返回记录限制数量
	 * @return 非NULL的list
	 */
	public List<DBObject> nearSphere(String collection, String locationField,
			Point center, long minDistance, long maxDistance, DBObject query,
			DBObject fields, int limit);

	/**
	 * 查询位于指定一个封闭多边形内的所有坐标点,给定的多边形坐标点必须首位相接形成封闭的多边形 如三角形 final
	 * LinkedList<double[]> polygon = new LinkedList<>(); polygon.addLast(new
	 * double[] { 121.36, 31.18 }); polygon.addLast(new double[] { 121.35, 31.36
	 * }); polygon.addLast(new double[] { 121.39, 31.17 }); polygon.addLast(new
	 * double[] { 121.36, 31.18 });
	 * 
	 * MongoDB将多边形的边界也作为查询形状的一部分
	 * 
	 * @param collection
	 *            集合名称
	 * @param locationField
	 *            坐标字段
	 * @param polygon
	 *            多边形坐标
	 * @param fields
	 *            查询字段
	 * @param query
	 *            查询条件
	 * @param limit
	 *            返回记录限制数量
	 * @return 非NULL的list
	 */
	public List<DBObject> withinPolygon(String collection,
			String locationField, List<double[]> polygon, DBObject fields,
			DBObject query, int limit);

	/**
	 * 查询位于指定多个封闭多边形内的所有坐标点,给定的多边形坐标点必须首位相接形成封闭的多边形
	 * 
	 * @param collection
	 *            集合名称
	 * @param locationField
	 *            坐标字段
	 * @param polygons
	 *            多边形坐标 数组
	 * @param fields
	 *            查询字段
	 * @param query
	 *            查询条件
	 * @param limit
	 *            返回记录限制数量
	 * @return 非NULL的list
	 */
	public List<DBObject> withinMultiPolygon(String collection,
			String locationField, List<List<double[]>> polygons,
			DBObject fields, DBObject query, int limit);

	/**
	 * 在矩形区域内查找坐标点,该方法仅仅在2d索引是支持,在2dsphere中不支持
	 * 
	 * @param collection
	 *            集合名称
	 * @param locationField
	 *            坐标字段
	 * @param bottomLeft
	 *            左下角
	 * @param upperRight
	 *            右上角
	 * @param fields
	 *            查询字段
	 * @param query
	 *            查询条件
	 * @param limit
	 *            返回记录限制数量
	 * @return 非NULL的list
	 */
	@Deprecated
	public List<DBObject> withinBox(String collection, String locationField,
			Point bottomLeft, Point upperRight, DBObject fields,
			DBObject query, int limit);

}</span><span style="font-size: 15px;">
</span>


5、mongodb 服务实现类

package com.spring.operation;

import com.mongodb.AggregationOptions;  
import com.mongodb.BasicDBObject;  
import com.mongodb.Cursor;  
import com.mongodb.DBObject;  
import com.spring.entity.Point;
import com.spring.mongodb.MongoGeoDao;  
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
import org.springframework.beans.factory.annotation.Autowired;  
import org.springframework.data.mongodb.core.MongoTemplate;   
import java.util.ArrayList;  
import java.util.LinkedList;  
import java.util.List;  

public class MongoDaoImpl implements MongoGeoDao {  
    
    private static Logger logger = LoggerFactory.getLogger(MongoDaoImpl.class);  
      
    @Autowired  
    private MongoTemplate mongoTemplate;  
   
   
    public DBObject findOne(String collection, DBObject query, DBObject fields) {  
        return mongoTemplate.getCollection(collection).findOne(query, fields);  
    }  
   
   
    public List<DBObject> find(String collection, DBObject query, DBObject fields, DBObject orderBy, int pageNum, int pageSize) {  
        List<DBObject> list = new ArrayList<DBObject>();  
        Cursor cursor = mongoTemplate.getCollection(collection).find(query, fields).skip((pageNum - 1) * pageSize).limit(pageSize).sort(orderBy);  
        while (cursor.hasNext()) {  
            list.add(cursor.next());  
        }  
        return list.size() > 0 ? list : null;  
    }  
   
 
    public List<DBObject> find(String collection, DBObject query, DBObject fields, DBObject orderBy, int limit) {  
        List<DBObject> list = new ArrayList<DBObject>();  
        Cursor cursor = mongoTemplate.getCollection(collection).find(query, fields).sort(orderBy).limit(limit);  
        while (cursor.hasNext()) {  
            list.add(cursor.next());  
        }  
        return list.size() > 0 ? list : null;  
    }  
   
   
    public void delete(String collection, DBObject dbObject) {  
        mongoTemplate.getCollection(collection).remove(dbObject);  
    }  
   
  
    public void save(String collection, DBObject dbObject) {  
        mongoTemplate.getCollection(collection).save(dbObject);  
    }  
   
 
    public void update(String collection, DBObject query, DBObject update, boolean upsert, boolean multi) {  
        mongoTemplate.getCollection(collection).update(query, update, upsert, multi);  
    }  
   
   
    public Long count(String collection, DBObject query) {  
        return mongoTemplate.getCollection(collection).count(query);  
    }  
   

    public List<?> distinct(String collection, String key, DBObject query) {  
        return mongoTemplate.getCollection(collection).distinct(key, query);  
    }  
   
  
    public List<DBObject> geoNear(String collection, DBObject query, Point point, int limit, long maxDistance) {  
        if(query==null)  
            query = new BasicDBObject();  
   
        List<DBObject> pipeLine = new ArrayList<DBObject>();  
        BasicDBObject aggregate = new BasicDBObject("$geoNear",  
        	    new BasicDBObject("near",new BasicDBObject("type","Point").append("coordinates",new double[]{point.getLng(), point.getLat()}))    
        				.append("distanceField","dist.calculated")  
                        .append("query", query)  
                        .append("num", limit)  
                        .append("maxDistance", maxDistance)  
                        .append("spherical",true)  
                );  
        pipeLine.add(aggregate);  
        Cursor cursor=mongoTemplate.getCollection(collection).aggregate(pipeLine, AggregationOptions.builder().build());  
        List<DBObject> list = new LinkedList<DBObject>();  
        while (cursor.hasNext()) {  
            list.add(cursor.next());  
        }  
        return list;  
    }  
   
 
    public List<DBObject> withinCircle(String collection,String locationField, Point center,  
                                       long radius, DBObject fields, DBObject query, int limit) {  
        LinkedList<Object> circle = new LinkedList<Object>();  
        //Set the center coordinate  
        circle.addLast(new double[]{center.getLng(),center.getLat()});  
        //Set the radius. unit:meter  
        circle.addLast(radius/6378137.0);  
   
        if(query==null)  
            query = new BasicDBObject();  
        query.put(locationField, new BasicDBObject("$geoWithin", new BasicDBObject("$centerSphere", circle)));  
        logger.info("withinCircle:{}",query.toString());  
        return mongoTemplate.getCollection(collection).find(query, fields).limit(limit).toArray();  
    }  
   
  
    public List<DBObject> nearSphere(String collection, String locationField, Point center,  
                                     long minDistance, long maxDistance, DBObject query, DBObject fields, int limit) {  
        if(query==null)  
            query = new BasicDBObject();  
   
        query.put(locationField,  
                new BasicDBObject("$nearSphere",  
                    new BasicDBObject("$geometry",  
                            new BasicDBObject("type","Point")  
                                    .append("coordinates",new double[]{center.getLng(),center.getLat()}))  
                            .append("$minDistance",minDistance)  
                            .append("$maxDistance",maxDistance)  
        ));  
        logger.info("nearSphere:{}",query.toString());  
        return mongoTemplate.getCollection(collection).find(query, fields).limit(limit).toArray();  
    }  
   
  
    public List<DBObject> withinPolygon(String collection, String locationField,  
                                        List<double[]> polygon, DBObject fields, DBObject query, int limit) {  
        if(query==null)  
            query = new BasicDBObject();  
   
        List<List<double[]>> polygons = new LinkedList<List<double[]>>();  
        polygons.add(polygon);  
        query.put(locationField, new BasicDBObject("$geoWithin",  
                new BasicDBObject("$geometry",  
                        new BasicDBObject("type","Polygon")  
                        .append("coordinates",polygons))));  
        logger.info("withinPolygon:{}",query.toString());  
        return mongoTemplate.getCollection(collection).find(query, fields).limit(limit).toArray();  
    }  
   
  
    public List<DBObject> withinMultiPolygon(String collection, String locationField, List<List<double[]>> polygons, DBObject fields, DBObject query, int limit) {  
        if(query==null)  
            query = new BasicDBObject();  
   
        List<List<List<double[]>>> list = new LinkedList<List<List<double[]>>>();  
        for (List<double[]> polygon : polygons) {  
            List<List<double[]>> temp = new LinkedList<List<double[]>>();  
            temp.add(polygon);  
            list.add(temp);  
        }  
        query.put(locationField, new BasicDBObject("$geoWithin",  
                new BasicDBObject("$geometry",  
                        new BasicDBObject("type","MultiPolygon")  
                                .append("coordinates",list))));  
        logger.info("withinMultiPolygon:{}",query.toString());  
        return mongoTemplate.getCollection(collection).find(query, fields).limit(limit).toArray();  
    }  
   
 
    public List<DBObject> withinBox(String collection, String locationField, Point bottomLeft, Point upperRight, DBObject fields, DBObject query, int limit) {  
        if(query==null)  
            query = new BasicDBObject();  
   
        LinkedList<double[]> box = new LinkedList<double[]>();  
        box.add(new double[]{bottomLeft.getLng(), bottomLeft.getLat()});  
        box.add(new double[]{upperRight.getLng(), upperRight.getLat()});  
   
        query.put(locationField, new BasicDBObject("$geoWithin", new BasicDBObject("$box", box)));  
        logger.info("withinBox:{}",query.toString());  
        return mongoTemplate.getCollection(collection).find(query, fields).limit(limit).toArray();  
    }  
   
}  

6、添加数据

db.point.test.insert({"address" : "南京 禄口国际机场","loc" : { "type": "Point", "coordinates": [118.783799,31.979234]}})  
db.point.test.insert({"address" : "南京 浦口公园","loc" : { "type": "Point", "coordinates": [118.639523,32.070078]}})  
db.point.test.insert({"address" : "南京 火车站","loc" : { "type": "Point", "coordinates": [118.803032,32.09248]}})  
db.point.test.insert({"address" : "南京 新街口","loc" : { "type": "Point", "coordinates": [118.790611,32.047616]}})  
db.point.test.insert({"address" : "南京 张府园","loc" : { "type": "Point", "coordinates": [118.790427,32.03722]}})  
db.point.test.insert({"address" : "南京 三山街","loc" : { "type": "Point", "coordinates": [118.788135,32.029064]}})  
db.point.test.insert({"address" : "南京 中华门","loc" : { "type": "Point", "coordinates": [118.781161,32.013023]}})  
db.point.test.insert({"address" : "南京 安德门","loc" : { "type": "Point", "coordinates": [118.768964,31.99646]}})


7、必须加索引 (为什么:https://docs.mongodb.com/manual/reference/operator/aggregation/geoNear/)
db.集合名称.ensureIndex( { loc : "2dsphere" } )  

8、调用实例

package com.spring.main;

import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.spring.entity.BusinessPosition;
import com.spring.entity.Point;
import com.spring.entity.Positions;
import com.spring.operation.BusinessPositionDao;
import com.spring.operation.MongoDaoImpl;

@RunWith(SpringJUnit4ClassRunner.class)  //使用junit4进行测试    
@ContextConfiguration(locations={"classpath*:mongodb.xml"}) 

public class DistanceMain {
	@Autowired 
	private BusinessPositionDao businessPositionDao;
	@Autowired 
	private MongoDaoImpl mongoDaoImpl;

	 @Test  
	 public void test1(){  		 
		 DBObject object = new BasicDBObject();
		 object.put("address", "南京 安德门");
		 DBObject subObject = new BasicDBObject();
		 subObject.put("type", "Point");
		 double[] addre = new double[2];
		 addre[0] = 118.768964;
		 addre[1] = 31.99646;
		 subObject.put("coordinates",addre);
		 object.put("loc", subObject);
		 mongoDaoImpl.save("positions",object);
		 System.out.println("数据插入成功");
	 }
	 
	 @Test  
	 public void test2(){  
		double lng = 118.768964;
		double lat = 31.99656;
		
		Point point = new Point(); 
		point.setLat(lat);
		point.setLng(lng);
		DBObject query = new BasicDBObject();
		int limit =10;
		long maxDistance = 1000;
		List<DBObject> list = mongoDaoImpl.geoNear("positions", query, point, limit, maxDistance);
		if(list !=null && list.size()>0){
			for(DBObject obj:list){
				System.out.println("商家地址:"+(String)obj.get("address"));
			}
		}
		
		
		
		
	 }

}<span style="font-size: 15px;">
</span>





  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值