如何从NoSQL DBMS(如DynamoDB)存储GPS坐标并搜索半径内的位置

如何从NoSQL DBMS(如DynamoDB)存储GPS坐标并搜索半径内的位置,nosql,gis,database,coordinate,Nosql,Gis,Database,Coordinate,我的团队需要像DynamoDB这样的DBMS来存储大量数据,主要是位置和坐标。 我曾考虑过使用一些基于GIS的DBMS(如PostGIS),并在该点上建立索引,但DynamoDB似乎非常适合我们使用 存储坐标并快速检索特定半径内所有对象的最佳方法是什么? 在PostGIS中,这很简单,如下所示: SELECT * FROM places WHERE ST_DWithin(coordinate, ST_GeomFromText('POINT(45.07085 7.68434)', 4326), 1

我的团队需要像DynamoDB这样的DBMS来存储大量数据,主要是位置和坐标。 我曾考虑过使用一些基于GIS的DBMS(如PostGIS),并在该点上建立索引,但DynamoDB似乎非常适合我们使用

存储坐标并快速检索特定半径内所有对象的最佳方法是什么? 在PostGIS中,这很简单,如下所示:

SELECT *
FROM places
WHERE ST_DWithin(coordinate, ST_GeomFromText('POINT(45.07085 7.68434)', 4326), 100.0);

我如何在NoSQL DBMS中做到这一点?

我目前正在研究这个课题。我正在使用MongoDb(我知道您要求使用DynamoDb,但您也要求使用一般的NoSql),我的代码如下所示:

SELECT *
FROM places
WHERE ST_DWithin(coordinate, ST_GeomFromText('POINT(45.07085 7.68434)', 4326), 100.0);
记录结构:

public class FrameDocument
{
    [BsonId]
    public Guid Id { get; set; }

    [BsonElement("coordinates")]
    public Point[] Polygon { get; set; }
}

public class Point
{
    [BsonElement("name")]
    public string Orientation { get; set; }

    [BsonElement("loc")]
    public double[] Location { get; set; }
}
连接和确保索引:

MongoServer server = MongoServer.Create(connectionString);
MongoDatabase database = server.GetDatabase(databaseName);
database.GetCollection(collectionName).EnsureIndex(IndexKeys.GeoSpatial("coordinates.loc"));
写作:

var items = database.GetCollection(collectionName);
items.InsertBatch(itemsToInsert);
搜索:

double[,] points; // define you search coordinates
var items = database.GetCollection<FrameDocument>(collectionName);
var query = Query.WithinPolygon("coordinates.loc", points);
var cursor = items.Find(query);
双[,]点;//定义搜索坐标
var items=database.GetCollection(collectionName);
var query=query.WithinPolygon(“坐标.loc”,点);
var cursor=items.Find(查询);

我们遇到了同样的问题,我们特别使用AWS和DynamoDB。 我们通过使用CloudSearch服务解决了这个问题,每次我们在数据库中存储一些“地理搜索”数据时,我们都使用lat、lon作为过滤器对CloudSearch实例中的数据进行索引(为此,您必须在lat和lon上进行转换,将其转换为uint)

然后,假设您要在特定的lat/lon和半径上进行搜索,您计算相应的geobox(latmin、latmax、lonmin、lonmax)并使用特定的过滤器查询CloudSearch实例以检索数据的关键模式,然后您可以查询DynamoDB以获取信息

Java中的一些代码可以执行上述操作:

使用Tyler Coles提供的com.javadocmd.simplelatelng.window包中的矩形窗口,计算边界框并对lat/lon进行转换

RectangularWindow rectangularWindow = new RectangularWindow(newLatLng(location.getLat().doubleValue(), location.getLon().doubleValue()), radius.doubleValue(), radius.doubleValue(), LengthUnit.KILOMETER);
latMin = (long) ((180 + rectangularWindow.getMinLatitude()) * 100000);     
latMax = (long) ((180 + rectangularWindow.getMaxLatitude()) * 100000);
lonMin = (long) ((360 + rectangularWindow.getLeftLongitude()) * 100000);
lonMax = (long) ((360 + rectangularWindow.getRightLongitude()) * 100000);
然后是CloudSearch实例上的查询示例:

http://[SEARCHURL]/2011-02-01/search?bq=(和lat:22300347..22309340(和lon:28379282..28391589))


我不确定这是否是最好的解决方案,但这正是我们所想到的

您可以使用geohashing根据字符串而不是计算来查询附近的对象

Geohash将允许您将节点的位置存储到“bucket”中,然后可以在dynamodb中使用字符串作为范围或哈希键来查询“bucket”


这是一个用javascript编写的好例子,可以很容易地用其他语言重写。

只是想知道为什么需要将lat/lon值从双精度转换为整数?或者你的意思是将2个索引转换为单个索引?实际上,我正在使用uint字段(因此需要一个整数)将它们保存在CloudSearch中,该字段是无符号的(因此需要使其为正)。我这样做是因为当我查询CloudSearch时,我可以使用非常有用的“min..max”过滤器。仅供参考:亚马逊官方CloudSearch论坛提供了一篇关于使用CloudSearch进行地理搜索的文章: