MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

Sfere di query geospaziali MongoDB sovrapposte a punto singolo

Bene, sarebbe più bello se potessi usare un oggetto GeoJSON per rappresentare la posizione, ma al momento il i tipi supportati sono in realtà limitati quindi un tipo "Cerchio" che sarebbe l'ideale non è supportato.

Il più vicino che potresti fare è un "poligono" che approssima un cerchio, ma questo è probabilmente un po' troppo lavoro da costruire solo per questo scopo di query. L'altra cosa è fare questo e poi applicare $geoIntersects è che i risultati non verranno "ordinati" in base alla distanza dal punto di query. Questo sembra essere l'opposto dello scopo di trovare la "pizza più vicina" al punto di origine.

Fortunatamente esiste un $geoNear operazione aggiunta al framework di aggregazione a partire da MongoDB 2.4 e versioni successive. La cosa buona qui è che permette la "proiezione" di un campo di distanza nei risultati. Ciò consente quindi di eseguire il filtraggio logico sul server in quei punti che sono vincolati "entro il raggio" alla distanza dal punto di origine. Consente inoltre l'ordinamento anche sul server.

Ma dovrai comunque cambiare lo schema per supportare l'indice

db.places.insert({
    "name": "Pizza Hut",
    "location": { 
        "type": "Point",
        "coordinates": [
            151.00211262702942,
            -33.81696995135973
        ]
    },
    "radius": 20
})

db.places.ensureIndex({ "location": "2dsphere" })

E per la query di aggregazione:

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 } }
])

Fondamentalmente questo dice,

Ci sono altre opzioni che puoi passare a $geoNear per perfezionare il risultato, oltre a restituire più dei 100 risultati predefiniti se necessario e sostanzialmente passare altre opzioni da interrogare come un "tipo" o un "nome" o qualsiasi altra informazione che hai sul documento.