Como armazenar coordenadas GPS e pesquisar locais em um raio de um DBMS NoSQL (como DynamoDB)

StackOverflow https://stackoverflow.com//questions/10691547

Pergunta

Minha equipe precisa de um SGBD como o DynamoDB para armazenar grande quantidade de dados, principalmente locais e coordenadas.Considerei usar alguns DBMS baseados em GIS (como PostGIS) com um índice no POINT, mas o DynamoDB parece ótimo para nosso uso.

Qual é o melhor método para armazenar as coordenadas e recuperar rapidamente todos os objetos em um determinado raio?

No PostGIS é fácil, algo assim:

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

Como posso fazer algo assim em um SGBD NoSQL?

Foi útil?

Solução

Tivemos o mesmo problema, estamos usando AWS e DynamoDB em particular.Resolvemos esse problema usando o CloudSearch Service, toda vez que armazenamos alguns dados 'geo-pesquisáveis' em nosso banco de dados, indexamos os dados em uma instância do CloudSearch com lat,lon como filtros (para fazer isso você tem que fazer uma transformação em lat e lon para transformá-lo em um uint ).

Então, digamos que você queira fazer uma pesquisa em uma lat/lon e raio específicos, você calcula a geobox correspondente ( latina, latmax , lonmin, lonmax ) e consulta sua instância do CloudSearch com os filtros específicos para recuperar o esquema principal de seus dados, você pode então consultar o DynamoDB para obter as informações.

Algum código em Java para fazer exatamente o que foi dito acima:

Usando RectangularWindows do pacote com.javadocmd.simplelatlng.window de Tyler Coles, calculando a caixa delimitadora e fazendo a transformação para 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);

Em seguida, um exemplo de consulta na instância do CloudSearch:

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

Não tenho certeza se é a melhor solução, mas foi isso que encontramos

Outras dicas

Você poderia usar geohashing para fazer consultas de objetos próximos com base em strings em vez de cálculos.

Geohash permitirá que você armazene a localização dos nós em "baldes" que podem ser consultados usando strings como um intervalo ou chave hash no dinamodb.

Aqui está um bom exemplo https://github.com/davetroy/geohash-js feito em javascript que pode ser facilmente reescrito em outras linguagens.

Atualmente estou pesquisando esse assunto sozinho.Estou usando o MongoDb (sei que você pediu o DynamoDb, mas também pediu o uso geral do NoSql) e meu código está assim:

estrutura de registro:

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; }
}

conectando e garantindo o índice:

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

escrita:

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

procurando:

double[,] points; // define you search coordinates
var items = database.GetCollection<FrameDocument>(collectionName);
var query = Query.WithinPolygon("coordinates.loc", points);
var cursor = items.Find(query);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top