autfish

导航

MongoDB-JAVA-Driver 3.2版本常用代码全整理(4) - 地理空间索引

MongoDB的3.x版本Java驱动相对2.x做了全新的设计,类库和使用方法上有很大区别。例如用Document替换BasicDBObject、通过Builders类构建Bson替代直接输入$命令等,本文整理了基于3.2版本的常用增删改查操作的使用方法。为了避免冗长的篇幅,分为增删改、查询、聚合、地理索引等几部分。

随着移动设备的普及,基于坐标和经纬度的位置查询变得越来越流行,例如查找离当前位置最近的N辆出租车。Mongodb专门针对这种查询建立了地理空间索引:2d和2dsphere索引。2d用于平面基于坐标的位置计算,2dsphere主要用于球体,比如地球,提供了基于弧度的位置计算。

import static com.mongodb.client.model.Indexes.geo2d;
import static com.mongodb.client.model.Indexes.geo2dsphere;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.bson.Document;

import com.mongodb.Block;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.geojson.LineString;
import com.mongodb.client.model.geojson.Point;
import com.mongodb.client.model.geojson.Polygon;
import com.mongodb.client.model.geojson.Position;

public class GeospatialExamples {

	public static void main(String[] args) throws ParseException {
		MongoClient mongoClient = new MongoClient("localhost", 27017);
		MongoDatabase database = mongoClient.getDatabase("lesson");
		
		GeospatialExamples client = new GeospatialExamples(database);
		client.show();
		mongoClient.close();
	}
	
	private MongoDatabase database;
	public GeospatialExamples(MongoDatabase database) {
		this.database = database;
	}
	
	public void show() {
		MongoCollection<Document> mc = database.getCollection("people");
		mc.drop();
		
		Document doc1 = new Document("name", "tom").append("raid", Arrays.asList(10, 10)).append("gps", new Point(new Position(10, 10)));
		Document doc2 = new Document("name", "jone").append("raid", Arrays.asList(10.1, 10)).append("gps", new Point(new Position(10.1, 10)));
		Document doc3 = new Document("name", "john").append("raid", Arrays.asList(10, 10.1)).append("gps", new Point(new Position(10, 10.1)));
		Document doc4 = new Document("name", "jack").append("raid", Arrays.asList(9.9, 10)).append("gps", new Point(new Position(9.9, 10)));
		Document doc5 = new Document("name", "mary").append("raid", Arrays.asList(10, 9.9)).append("gps", new Point(new Position(10, 9.9)));
		Document doc6 = new Document("name", "abby").append("raid", Arrays.asList(10.2, 10)).append("gps", new Point(new Position(10.2, 10)));
		Document doc7 = new Document("name", "adam").append("raid", Arrays.asList(10.3, 10)).append("gps", new Point(new Position(10.3, 10)));
		Document doc8 = new Document("name", "barry").append("raid", Arrays.asList(10.4, 10)).append("gps", new Point(new Position(10.4, 10)));
		Document doc9 = new Document("name", "anne").append("raid", Arrays.asList(10.5, 10)).append("gps", new Point(new Position(10.5, 10)));
		mc.insertMany(Arrays.asList(doc1, doc2, doc3, doc4, doc5, doc6, doc7, doc8, doc9));
		
		mc.createIndex(geo2d("raid"));
		mc.createIndex(geo2dsphere("gps"));
		
		//$geoWithin 匹配任意几何图形内搜索
		FindIterable<Document> iterable = mc.find(Filters.geoWithin("raid", new Polygon(Arrays.asList(new Position(10.2, 10), new Position(10, 10.2), new Position(9.8, 10), new Position(10, 9.8), new Position(10.2, 10)))));
		printResult("Filters.geoWithin raid", iterable);
		
		//$geoWithinBox 在以左下角和右上角坐标构成方形内搜索
		iterable = mc.find(Filters.geoWithinBox("raid", 9.8, 9.8, 10.2, 10.2));
		printResult("Filters.geoWithinBox raid", iterable);
		
		//$geoWithinPolygon 在多边形内搜索
		List<Double> p1 = new ArrayList<>();
		List<Double> p2 = new ArrayList<>();
		List<Double> p3 = new ArrayList<>();
		p1.add(10d);
		p1.add(10d);
		p2.add(10.1);
		p2.add(10.16);
		p3.add(10.2);
		p3.add(10d);
		List<List<Double>> polygon = Arrays.asList(p1, p2, p3);
		iterable = mc.find(Filters.geoWithinPolygon("raid", polygon));
		printResult("Filters.geoWithinPolygon raid", iterable);

		p2.clear();
		p2.add(9.9);
		p2.add(10.16);
		p3.clear();
		p3.add(9.8);
		p3.add(10d);
		polygon = Arrays.asList(p1, p2, p3);
		iterable = mc.find(Filters.geoWithinPolygon("gps", polygon));
		printResult("Filters.geoWithinPolygon gps", iterable);
		
		//$geoWithinCenter 在指定圆心和半径的圆形内搜索
		iterable = mc.find(Filters.geoWithinCenter("raid", 10d, 10d, 0.25));
		printResult("Filters.geoWithinCenter raid", iterable);
		
		//$geoWithinCenterSphere 在球体(地球)上指定圆心和弧度搜索, 例如搜索以[10,10]为中心500米内的文档, 参数为...10d, 10d, 0.5/6371
		iterable = mc.find(Filters.geoWithinCenterSphere("gps", 10d, 10d, 11d/6371));
		printResult("Filters.geoWithinCenterSphere gps", iterable);

		//$geoIntersects
		iterable = mc.find(Filters.geoIntersects("gps", new LineString(Arrays.asList(new Position(10, 10.1), new Position(10.1, 10), new Position(10, 9.9)))));
		printResult("Filters.geoIntersects gps", iterable);
		
		//$near
		iterable = mc.find(Filters.near("gps", new Point(new Position(10, 10)), 20566d, 0d));
		printResult("Filters.near gps", iterable);
		
		//$nearSphere
		iterable = mc.find(Filters.nearSphere("gps", new Point(new Position(10, 10)), 20566d, 10d));
		printResult("Filters.nearSphere gps", iterable);
	}
	
	public void printResult(String doing, FindIterable<Document> iterable) {
		System.out.println(doing);
        iterable.forEach(new Block<Document>() {
            public void apply(final Document document) {
                System.out.println(document);
            }
        });
        System.out.println("------------------------------------------------------");
        System.out.println();
	}
}


posted on 2016-05-18 09:11  autfish  阅读(1085)  评论(0编辑  收藏  举报