spring mongodb geo 位置搜索服务 示例解析

无情 阅读:213 2021-03-31 21:40:01 评论:0

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>





声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

发表评论
搜索
排行榜
KIKK导航

KIKK导航

关注我们