SPRING DATA MONGDB空间索引(判断一个点POINT是否在一个区域POLYGON内)
这里要连接 MongoDB 数据库,在配置文件里:spring.data.mongodb.uri = mongodb://root:root@localhost:27017/happy
两个 root 分别是用户名和密码,happy 是数据库名。
首先创建一个实体类 SiteExt.java
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.index.CompoundIndex;
import org.springframework.data.mongodb.core.index.CompoundIndexes;
import org.springframework.data.mongodb.core.mapping.Document;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "SiteExt")
@CompoundIndexes({
@CompoundIndex(name = "location_index", def = "{'location':'2dsphere'}"),
})
public class SiteExt {
@Id
private String plateNo;
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> GeoJsonPoint <span style="color: rgba(255, 0, 0, 1)">location</span>;
}
注意这里使用了2dsphere索引
{'location': '2dsphere'}
测试用的就不再规范地写接口了,只写个实现类了。
SiteExtDao.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.BulkOperations;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.geo.GeoJsonPolygon;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Repository;
import xy.study.mongdb.model.SiteExt;
import java.util.List;
@Repository
public class SiteExtDao {
@Autowired
</span><span style="color: rgba(0, 0, 255, 1)">private</span><span style="color: rgba(0, 0, 0, 1)"> MongoTemplate mongoTemplate;
</span><span style="color: rgba(0, 0, 255, 1)">public</span> List<SiteExt><span style="color: rgba(0, 0, 0, 1)"><span style="color: rgba(255, 0, 0, 1)"> findPointInPolygon</span>(<span style="color: rgba(255, 0, 0, 1)">GeoJsonPolygon</span> geoJsonPolygon, String collectionName) {
Query query </span>= <span style="color: rgba(0, 0, 255, 1)">new</span> Query(Criteria.where("<span style="color: rgba(255, 0, 0, 1)">location</span>"<span style="color: rgba(0, 0, 0, 1)">).<span style="color: rgba(255, 0, 0, 1)">within</span>(geoJsonPolygon));
List</span><SiteExt> list = mongoTemplate.find(query, SiteExt.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">,collectionName);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> list;
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span><span style="color: rgba(0, 0, 0, 1)"> insert(SiteExt siteExt, String collectionName) {
mongoTemplate.insert(siteExt,collectionName);
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> <span style="color: rgba(0, 0, 255, 1)">void</span> insertBatch(List<SiteExt><span style="color: rgba(0, 0, 0, 1)"> list, String collectionName) {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> BulkMode.UNORDERED:表示并行处理,遇到错误时能继续执行不影响其他操作;BulkMode.ORDERED:表示顺序执行,遇到错误时会停止所有执行</span>
BulkOperations ops =<span style="color: rgba(0, 0, 0, 1)"> mongoTemplate.bulkOps(BulkOperations.BulkMode.UNORDERED, collectionName);
ops.insert(list);
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 执行操作</span>
ops.execute();
}
</span><span style="color: rgba(0, 0, 255, 1)">public</span> List<SiteExt><span style="color: rgba(0, 0, 0, 1)"> findAll(String collectionName) {
Query query</span>=<span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Query();
List</span><SiteExt> list = mongoTemplate.find(query, SiteExt.<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)">,collectionName);
</span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> list;
}
}
注意这里创建查询条件这里:Query query = new Query(Criteria.where("location").within(geoJsonPolygon));
location 是实体类 SiteExt 中建立了2dsphere 索引的字段名,再调用within方法,传入区域对象 GeoJsonPloygon。
GeoJsonPlaygon 代表的是一个区域对象,这个类在 org.springframework.data.mongodb.core.geo 包下面。
先插入两条数据做测试:
@Autowired
private SiteExtDao siteExtDao;
GeoJsonPoint geoJsonPoint1 = new GeoJsonPoint(new Point(113.330908,23.155678));
SiteExt siteExt1 = new SiteExt("A",geoJsonPoint1);
GeoJsonPoint geoJsonPoint2 = new GeoJsonPoint(new Point(113.33831,23.137335));
SiteExt siteExt2 = new SiteExt("B",geoJsonPoint2);
siteExtDao.insert(siteExt1,"SiteExt");
siteExtDao.insert(siteExt2,"SiteExt");
然后查询哪些点在指定区域的操作来了:
Point p1 = new Point(113.314882,23.163055);
Point p2 = new Point(113.355845,23.167042);
Point p3 = new Point(113.370289,23.149564);
Point p4 = new Point(113.356779,23.129758);
Point p5 = new Point(113.338238,23.13913);
Point p6 = new Point(113.330979,23.124706);
Point p7 = new Point(113.313588,23.140858);
Point p8 = new Point(113.323865,23.158204);
Point p9 = new Point(113.314882,23.163055);
List</span><Point> list = <span style="color: rgba(0, 0, 255, 1)">new</span> ArrayList<><span style="color: rgba(0, 0, 0, 1)">();
list.add(p1);
list.add(p2);
list.add(p3);
list.add(p4);
list.add(p5);
list.add(p6);
list.add(p7);
list.add(p8);
list.add(p9);
// 用 9 个点围成一个区域,首尾两个点 p1 和 p9 要相同,才能构成一个区域
GeoJsonPolygon geoJsonPolygon = new GeoJsonPolygon(list);
// 传入区域和数据库表名
List<SiteExt> pointInPolygon = siteExtDao.findPointInPolygon(geoJsonPolygon,"SiteExt");
pointInPolygon.forEach(
p -> {
System.out.println(p.getLocation());
}
);
上面 9 个点围成了一个多边形,在 "SiteExt" 表中查询哪些记录在这个多边形区域中。
结果如下:
Point [x=113.330908, y=23.155678]
总结:就是建立2dsphere 索引,利用查询语句Query query = new Query(Criteria.where("location").within(geoJsonPolygon)) 查询符合该区域的所有点;
MongoDB 原生查询数据表中哪些点记录在指定的区域:https://www.jb51.net/article/105796.htm