我有一个地方集合,明确地将位置存储为
place = {
name : "",
latitude: "",
longitude:""
}
有没有办法使用mongo shell或spring数据mongo我可以查询这样的地方:
select all places with coordinates(places.longitude, place.latitude) near a point(x,y) and within a distance z . Something like:
db.places.find( {
{
"type" : "Point",
"coordinates" : [
places.longitude,
places.latitude
]
}:
{ $geoWithin:
{ $centerSphere: [ [ x, y ] ,z / 3963.2 ]
}
}
})
或者我必须将我的收藏修改为
place = {
name : "",
"loc" : {
"type" : "Point",
"coordinates" : [
longitude,
latitude
]
}
}
答案 0 :(得分:1)
你真的应该改变你的数据。 MongoDB仅支持传统坐标对格式或GeoJSON,仅支持地理索引和查询。您不能以任何方式对数据使用不同的字段或“转换”,因为使用$near
或$nearSphere
的操作所需的“索引”需要支持的字段格式。
最好转换到shell中的转换,因为为“一次性”操作编写其他API代码是不必要的。是的,你真的应该使用GeoJSON格式:
var bulk = db.places.initializeUnorderedBulkOp(),
count = 0;
db.places.find().forEach(function(doc) {
bulk.find({ "_id": doc._id }).updateOne({
"$set": {
"location": {
"type": "Point",
"coordinates": [parseFloat(doc.longitude),parseFloat(doc.latitude)]
}
},
"$unset": { "latitude": "", "longitude": "" }
});
count++;
if ( count % 1000 == 0 ) {
bulk.execute();
bulk = db.places.initializeUnorderedBulkOp();
}
});
if ( count % 1000 !=0 )
bulk.execute();
现在数据已修复并与索引兼容,创建索引。这里使用GeoJSON数据有意义的是"2sphere"索引:
db.places.createIndex({ "location": "2dsphere" })
之后,您可以正常查询文档:
db.places.find({
"location": {
"$geoWithin": {
"$centerSphere": [ [ x, y ] ,z]
}
}
})
我还应该注意,$centreSphere
中的$geoWithin
操作实际上与$nearSphere
修饰符的$geoWithin
操作相同。唯一的例外是后者应该“更快”处理以及为“最近”的位置生成“有序”结果,这是db.places.find({
"$nearSphere": {
"$geometry": {
"type": "Point",
"coordinates": [x,y]
},
"$maxDistance": z
}
})
不能做的事情:
db.places.aggregate([
{ "$project": {
"name": 1
"location": {
"type": "Point",
"coordinates": {
"$map": {
"input": ["A","B"],
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el", "A" ] },
"$longitude",
"$latitude"
]
}
}
}
}
}},
{ "$match": {
"location": {
"$geoWithin": {
"$centerSphere": [ [ x, y ] ,z]
}
}
}}
])
对现有数据执行此操作的唯一方法是仅$maxDistance
。这是因为该操作不需要地理空间索引,因此您可以首先“转换”文档。
您可以使用$geoWithin
方法和.aggregate()
管道阶段以及$project
运算符执行此操作:
$nearSphere
但是您的经度和纬度数据必须已经是数字,因为这是您无法在聚合框架中转换的内容。并且您必须记住,不能用于customer
之类的操作,因为在初始管道阶段之后所需的索引不可用。
所以可以做到,但这是不可取的。这将增加处理时间,如果您修复数据并添加适当的索引,事情会变得更好,更灵活,更“快”。
另请注意,GeoJSON数据的所有距离均以公里为单位,而不是弧度。