Bem, seria melhor se você pudesse usar um objeto GeoJSON para representar o local, mas a partir de agora o os tipos suportados são realmente limitados portanto, um tipo "Círculo" que seria ideal não é suportado.
O mais próximo que você pode fazer é um "Polygon" aproximando um círculo, mas isso provavelmente é um pouco trabalhoso para construir apenas para essa finalidade de consulta. A outra pegadinha é fazer isso e depois aplicar
$geoIntersects
é que os resultados não serão "ordenados" pela distância do ponto de consulta. Isso parece ser o contrário do propósito de encontrar a “pizza mais próxima” do ponto de origem. Felizmente, existe um
$geoNear
operação adicionada à estrutura de agregação a partir do MongoDB 2.4 e superior. O bom aqui é que permite a "projeção" de um campo de distância nos resultados. Isso permite que você faça a filtragem lógica no servidor para os pontos que estão "dentro do raio" da restrição à distância do ponto de origem. Também permite a classificação no servidor. Mas você ainda precisará alterar seu esquema para suportar o índice
db.places.insert({
"name": "Pizza Hut",
"location": {
"type": "Point",
"coordinates": [
151.00211262702942,
-33.81696995135973
]
},
"radius": 20
})
db.places.ensureIndex({ "location": "2dsphere" })
E para a consulta de agregação:
db.places.aggregate([
// Query and project distance
{ "$geoNear": {
"near": {
"type": "Point",
"coordinates": [
150.92094898223877,
-33.77654333272719
]
},
"distanceField": "distance",
"distanceMultiplier": 0.001,
"maxDistance": 100000,
"spherical": true
}},
// Calculate if distance is within delivery sphere
{ "$project": {
"name": 1,
"location": 1,
"radius": 1,
"distance": 1,
"within": { "$gt": [ "$radius", "$distance" ] }
}},
// Filter any false results
{ "$match": { "within": true } },
// Sort by shortest distance from origin
{ "$sort": { "distance": -1 } }
])
Basicamente isso diz,
Existem outras opções que você pode passar para
$geoNear
para refinar o resultado, bem como retornar mais do que os 100 resultados padrão se necessário e basicamente passar outras opções de consulta como um "tipo" ou "nome" ou qualquer outra informação que você tenha no documento.