MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Encontre um local dentro de um círculo armazenado


Ainda mais otimizado que o original, agora você pode usar $expr dentro de um $match estágio após o $geoNear inicial :
db.collection.aggregate([
    { "$geoNear": {
        "near": {
            "type": "Point",
            "coordinates": [ 23.027573, 72.50675800000001 ],
        },
        "distanceField": "distance"
    }},
    { "$match": { "$expr": { "$lte": [ "$distance", "$radius" ] } }}
])

Na verdade, um pouco mais ideal do que quando escrito pela primeira vez. Agora podemos apenas $redact em vez de $project o booleano e $match mais tarde:
db.collection.aggregate([
    // Match documents "near" the queried point
    { "$geoNear": {
        "near": {
            "type": "Point",
            "coordinates": [ 23.027573, 72.50675800000001 ],
        },
        "distanceField": "distance"
    }},

    // Calculate if distance is within radius and remove if not
    { "$redact": {
        "$cond": {
            "if": { "$lte": [ "$distance", "$radius" ] },
            "then": "$$KEEP",
            "else": "$$PRUNE"
        }
    }}
])

Você armazenou as informações exatamente como deveria, mas há uma abordagem diferente para obter os resultados do que você imagina.

O que você deseja usar é um $geoNear e especificamente a estrutura de agregação forma desse operador. Aqui está o que você faz:
db.collection.aggregate([
    // Match documents "near" the queried point
    { "$geoNear": {
        "near": {
            "type": "Point",
            "coordinates": [ 23.027573, 72.50675800000001 ],
        },
        "distanceField": "distance"
    }},

    // Calculate if distance is within radius
    { "$project": {
        "location": 1,
        "radius": 1,
        "distance": 1,
        "within": { "$lte": [ "$distance", "$radius" ] }
    }},

    // Match only documents within the radius
    { "$match": { "within": true } }
])

Assim, esse formulário permite que a distância do ponto consultado seja "projetada" nos resultados, enquanto a consulta também retornará apenas os documentos mais próximos.

Então você usa uma comparação lógica para ver se o valor de "distância" é menor que "raio", portanto dentro do círculo.

Finalmente, você faz a correspondência para filtrar apenas os resultados em que a afirmação "dentro" era verdadeira.

Você pode adicionar outras opções a $geoNear conforme mostrado na documentação. Eu também sugiro fortemente que seu armazenamento também use o formato GeoJSON, pois provavelmente será mais compatível com quaisquer outras bibliotecas que você possa usar para trabalhar nos resultados obtidos.