node.js - index - mongoose $near
Mongoose llama a geoNear con puntos GeoJSON ya que los parĂ¡metros de consulta no funcionan (2)
El problema fue utilizar incorrectamente maxDistance. La siguiente expresión funcionó.
Branch.geoNear({type: "Point", coordinates: [0.0776590, -33.7797590]}, {
spherical: true,
maxDistance: 1 / 6378137,
distanceMultiplier: 6378137
})
.then(function (doc) {
console.log(doc);
process.exit();
});
Mongoose: branches.ensureIndex({ location: ''2dsphere'' }) { safe: undefined, background: true }
Mongoose: branches.geoNear(0.077659) -33.779759 { distanceMultiplier: 6378137, lean: true, maxDistance: 1.567855942887398e-7, spherical: true }
[]
Ahora la consulta descubre correctamente que los dos documentos en la colección no están dentro de 1 metro de la ubicación consultada. Consultar una ubicación más cercana a casa también nos da los resultados esperados.
Branch.geoNear({type: "Point", coordinates: [153.027117, -27.468515]}, {
spherical: true,
maxDistance: 1 / 6378137,
distanceMultiplier: 6378137
})
.then(function (doc) {
console.log(doc);
process.exit();
});
Mongoose: branches.ensureIndex({ location: ''2dsphere'' }) { safe: undefined, background: true }
Mongoose: branches.geoNear(153.027117) -27.468515 { distanceMultiplier: 6378137, lean: true, maxDistance: 1.567855942887398e-7, spherical: true }
[ { dis: 0.0026823704060803567,
obj:
{ name: ''A'',
_id: 533200e49ba06bec37c0cc22,
location: [Object],
__v: 0 } } ]
¿La solución?
La documentación de MongoDb de geoNear establece que si se usa un objeto geoJSON maxDistance debe estar en metros, y en radianes si se usan pares de coordenadas.
Opcional. Una distancia desde el punto central. Especifique la distancia en metros para los datos de GeoJSON y en radianes para los pares de coordenadas heredados. MongoDB limita los resultados a aquellos documentos que se encuentran dentro de la distancia especificada desde el punto central. http://docs.mongodb.org/manual/reference/command/geoNear/#dbcmd.geoNear
Esto es incorrecto o mi comprensión es incorrecta.
Como puede ver arriba, en lugar de especificar 1 metro para maxDistance, se suministra en radianes.
Como en la fecha de este post, GeoNear requiere que maxDistance esté en radianes, independientemente de si está utilizando un objeto geoJSON o un par de coordenadas heredado.
Dado un esquema definido para documentos que contienen una ubicación GeoJSON;
var BranchSchema = new Schema({
location: {
''type'': {
type: String,
required: true,
enum: [''Point'', ''LineString'', ''Polygon''],
default: ''Point''
},
coordinates: [Number]
},
name: String
});
BranchSchema.index({location: ''2dsphere''});
Y algunos datos de muestra:
[
{
"name": "A",
"location": {
"type": "Point",
"coordinates": [153.027117, -27.468515 ] //Brisbane, Australia
}
},
{
"name": "B",
"location": {
"type": "Point",
"coordinates": [153.029884, -27.45643] //Also Brisbane, Australia
}
}
]
La siguiente consulta geoNear no se comporta como se esperaba. Leí esta consulta como "dada una ubicación frente a la costa de América del Sur, rastrea las localizaciones y encuentra cualquiera que esté a 1 metro de la ubicación provista".
// Somewhere off the east coast of South America.
var point = {type: ''Point'', coordinates: [0.0776590, -33.7797590]};
Branch.geoNear(point, {maxDistance:1, spherical: true}, function (err, data) {
...
// at this point I expected data.length === 0.
// Instead it is returning both documents.
...
});
¿Qué estoy haciendo mal?
- Estoy utilizando [long, lat] cuando defino una posición según el estándar WGS84.
- Runnings MongooseJS V3.8.8
Mongoose estaba convirtiendo puntos geoJSON en pares de coordenadas heredados debido a una limitación en el controlador nativo; se ha agregado soporte al controlador nativo, y hay un PR abierto para agregar este soporte a Mongoose. He actualizado el problema proporcionado por @NickB.