spring java mongodb geo 位置搜索服务 示例

1、配置 pom.xml,在原有的spring项目中添加以下2个即可。

                <!-- mongo db 驱动-->
		<dependency>
		    <groupId>org.mongodb</groupId>
		    <artifactId>mongo-java-driver</artifactId>
		    <version>3.2.2</version>
		</dependency>
		
		<!-- spring-data-mongodb -->
		<dependency>
		    <groupId>org.springframework.data</groupId>
		    <artifactId>spring-data-mongodb</artifactId>
		    <version>1.9.2.RELEASE</version>
		</dependency>

2、配置 spring-data-mongo.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mongo="http://www.springframework.org/schema/data/mongo"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
 	http://www.springframework.org/schema/data/mongo
    http://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd">

	<!-- Default bean name is 'mongo' -->
	<mongo:mongo host="localhost" port="27017"/>
	
	<!-- Offers convenience methods and automatic mapping between MongoDB JSON documents and your domain classes. -->
  	<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
  			<constructor-arg ref="mongo"/>
		    <constructor-arg name="databaseName" value="test"/>
  	</bean>
</beans>

3、mongodb 父接口类


package com.zjp.cache;

import java.util.List;

import com.mongodb.DBObject;

/**
 * mongodb 父接口类
 * @author babylon
 * @version 1.1
 * @date 2016年7月12日-下午1:22: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);
 
}

4、Mondodb 地址运算 接口类


package com.zjp.cache;
 
import com.mongodb.DBObject;
 
import java.util.List;
 
/**
 * Mondodb 地址运算 接口类
 *
 * @author babylon
 * @version 1.1
 * @date 2016年7月12日-下午1:42: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);
 
}

5、mongodb 服务实现类


package com.zjp.service.impl;
 
import com.mongodb.AggregationOptions;
import com.mongodb.BasicDBObject;
import com.mongodb.Cursor;
import com.mongodb.DBObject;
import com.zjp.cache.MongoGeoDao;
import com.zjp.cache.Point;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
 
/**
 * mongodb 服务实现类
 *
 * @author babylon
 * @version 1.1
 * @date 2016年7月12日-下午1:36:50
 */
@Repository
public class MongoDaoImpl implements MongoGeoDao {
	
    private static Logger logger = LoggerFactory.getLogger(MongoDaoImpl.class);
    
    @Autowired
    private MongoTemplate mongoTemplate;
 
    @Override
    public DBObject findOne(String collection, DBObject query, DBObject fields) {
        return mongoTemplate.getCollection(collection).findOne(query, fields);
    }
 
    @Override
    public List<DBObject> find(String collection, DBObject query, DBObject fields, DBObject orderBy, int pageNum, int pageSize) {
        List<DBObject> list = new ArrayList<>();
        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;
    }
 
    @Override
    public List<DBObject> find(String collection, DBObject query, DBObject fields, DBObject orderBy, int limit) {
        List<DBObject> list = new ArrayList<>();
        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;
    }
 
    @Override
    public void delete(String collection, DBObject dbObject) {
        mongoTemplate.getCollection(collection).remove(dbObject);
    }
 
    @Override
    public void save(String collection, DBObject dbObject) {
        mongoTemplate.getCollection(collection).save(dbObject);
    }
 
    @Override
    public void update(String collection, DBObject query, DBObject update, boolean upsert, boolean multi) {
        mongoTemplate.getCollection(collection).update(query, update, upsert, multi);
    }
 
    @Override
    public Long count(String collection, DBObject query) {
        return mongoTemplate.getCollection(collection).count(query);
    }
 
	@Override
    public List<?> distinct(String collection, String key, DBObject query) {
        return mongoTemplate.getCollection(collection).distinct(key, query);
    }
 
    @Override
    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<>();
        BasicDBObject aggregate = new BasicDBObject("$geoNear",
	    		new BasicDBObject("near",new BasicDBObject("type","Point").append("coordinates",new double[]{118.783799, 31.979234}))
				        .append("distanceField","dist.calculated")
				        .append("query", new BasicDBObject())
				        .append("num", 5)
				        .append("maxDistance", 5000)
				        .append("spherical",true)
	    		);
        pipeLine.add(aggregate);
        Cursor cursor=mongoTemplate.getCollection(collection).aggregate(pipeLine, AggregationOptions.builder().build());
        List<DBObject> list = new LinkedList<>();
        while (cursor.hasNext()) {
            list.add(cursor.next());
        }
        return list;
    }
 
    @Override
    public List<DBObject> withinCircle(String collection,String locationField, Point center,
                                       long radius, DBObject fields, DBObject query, int limit) {
        LinkedList<Object> circle = new LinkedList<>();
        //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();
    }
 
    @Override
    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();
    }
 
    @Override
    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<>();
        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();
    }
 
    @Override
    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<>();
        for (List<double[]> polygon : polygons) {
            List<List<double[]>> temp = new LinkedList<>();
            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();
    }
 
    @Override
    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<>();
        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.point.test.ensureIndex( { loc : "2dsphere" } )  

8、调用实例

@Autowired
private MongoDaoImpl mongoDao;			
DBObject query = new BasicDBObject();
Point point = new Point();
point.setLng(118.783799);
point.setLat(31.979234);
int limit = 5;
Long maxDistance = 5000L; // 米
List<DBObject> list = mongoDao.geoNear("point.test", query, point, limit, maxDistance);
for(DBObject obj : list)
   System.out.println(obj);


1.了解Spring 2.了解NoSQL和文档数据库 3.要求 4.其他帮助资源 4.1。支持 4.1.1。社区论坛 4.1.2。专业支持 4.2。发展之后 5.新&值得注意的 5.1。Spring Data MongoDB 2.1中的新特性 5.2。Spring Data MongoDB 2.0中的新特性 5.3。Spring Data MongoDB 1.10中的新特性 5.4。Spring Data MongoDB 1.9中的新特性 5.5。Spring Data MongoDB 1.8中的新特性 5.6。Spring Data MongoDB 1.7中有什么新功能 6.依赖 6.1。Spring Boot的依赖管理 6.2。Spring框架 7.使用Spring Data Repositories 7.1。核心概念 7.2。查询方法 7.3。定义存储库接口 7.3.1。微调储存库定义 7.3.2。空处理存储库方法 7.3.3。将存储库与多个Spring Data模块一起使用 7.4。定义查询方法 7.4.1。查询查询策略 7.4.2。查询创建 7.4.3。属性表达式 7.4.4。特殊参数处理 7.4.5。限制查询结果 7.4.6。流式查询结果 7.4.7。异步查询结果 7.5。创建存储库实例 7.5.1。XML配置 7.5.2。JavaConfig 7.5.3。独立使用 7.6。Spring Data存储库的自定义实现 7.6.1。定制个人存储库 7.6.2。自定义基础存储库 7.7。从聚合根发布事件 7.8。Spring数据扩展 7.8.1。Querydsl扩展 7.8.2。Web支持 7.8.3。存储库填充程序 7.8.4。传统网络支持 参考文档 8.介绍 8.1。文档结构 9. MongoDB支持 9.1。入门 9.2。示例存储库 9.3。用Spring连接到MongoDB 9.3.1。使用基于Java的元数据注册Mongo实例 9.3.2。使用基于XML的元数据注册Mongo实例 9.3.3。MongoDbFactory接口 9.3.4。使用基于Java的元数据注册MongoDbFactory实例 9.3.5。使用基于XML的元数据注册MongoDbFactory实例 9.4。MongoTemplate简介 9.4.1。实例化MongoTemplate 9.4.2。WriteResultChecking策略 9.4.3。WriteConcern 9.4.4。WriteConcernResolver 9.5。保存,更新和删除文档 9.5.1。如何_id在映射图层中处理该字段 9.5.2。类型映射 9.5.3。保存和插入文件的方法 9.5.4。更新集合中的文档 9.5.5。在集合中插入文档 9.5.6。在集合中查找和插入文档 9.5.7。删除文件的方法 9.5.8。乐观锁定 9.6。查询文件 9.6.1。查询集合中的文档 9.6.2。查询文件的方法 9.6.3。查询不同的值 9.6.4。地理空间查询 9.6.5。GeoJSON支持 9.6.6。全文查询 9.6.7。排序规则 9.6.8。JSON模式 9.6.9。流利的模板API 9.7。按实例查询 9.7.1。介绍 9.7.2。用法 9.7.3。示例匹配器 9.7.4。执行一个例子 9.7.5。无类型示例 9.8。减少地图操作 9.8.1。使用示例 9.9。脚本操作 9.9.1。使用示例 9.10。集团运营 9.10.1。使用示例 9.11。聚合框架支持 9.11.1。基本概念 9.11.2。支持的聚合操作 9.11.3。投影表达式 9.11.4。分面分类 9.12。用自定义转换器覆盖默认映射 9.12.1。使用已注册的Spring Converter进行保存 9.12.2。使用Spring转换器读取 9.12.3。使用MongoConverter注册Spring转换器 9.12.4。转换器消除歧义 9.13。索引和集合管理 9.13.1。创建索引的方法 9.13.2。访问索引信息 9.13.3。使用集合的方法 9.14。执行命令 9.14.1。执行命令的方法 9.15。生命周期事件 9.16。例外翻译 9.17。执行回调 9.18。GridFS支持 9.19。更改流 9.19.1。使用MessageListener更改流 9.19.2。更改流 - 无效 10.反应性的MongoDB支持 10.1。入门 10.2。使用Spring和Reactive Streams Driver连接到MongoDB 10.2.1。使用基于Java的元数据注册MongoClient实例 10.2.2。ReactiveMongoDatabaseFactory接口 10.2.3。使用基于
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值