標籤:
1、配置 pom.xml,在原有的spring項目中添加以下2個即可。
<span style="white-space:pre"></span><!-- 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.xsdhttp://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.xsdhttp://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.xsdhttp://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 */@Repositorypublic 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、調用執行個體
@Autowiredprivate 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);
spring java mongodb geo 位置搜尋服務 樣本