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

Come definire un cerchio per uno schema mongo db?

Per essere valido per una "interrogazione geospaziale" la "posizione" deve essere in longitudine, latitudine ordine e non può contenere altre coordinate.

I formati validi sono

 { 
     "location": [long,lat]
 }

Oppure

 {
    "location": { "lng": long, "lat": lat }
 }

O GeoJSON

 {
     "location": {
         "type": "Point",
         "coordinates": [long,lat]
     }
 }

Un altro campo come "raggio" è "un altro campo" e non può far parte dello stesso array.

Idealmente segui GeoJSON:

 {
     "location": {
         "type": "Point",
         "coordinates": [long,lat]
     },
     "radius": radius
 }

Che nella definizione dello schema mangusta può essere semplice come:

var geoSchema = new Schema({
    "location": {
        "type": String,
        "coordinates": []
    },
    "radius": Number
});

Quando si tratta di dati geospaziali a coordinate "globo" reali, il proprio indice dovrebbe essere "2dsphere" , che puoi facoltativamente definire sullo schema come :

geoSchema.index({ "location": "2dsphere" })

Poiché non esiste un supporto effettivo per un oggetto "Cerchio" in GeoJSON supportato, si consiglia di mantenere un altro campo come "raggio" e di memorizzare il "punto centrale".

Il "grande" vantaggio di GeoJSON rispetto agli altri formati "legacy coordinate pairs" è che quando si restituisce qualcosa come una "distanza" da un punto tramite geoNear o $geoNear allora quella "distanza" è definita in "metri" in modo coerente. Questo è anche il modo in cui dovresti definire qualsiasi valore di "raggio" nella tua memoria per rimanere coerente con quel risultato.

Con gli altri formati di archiviazione, il risultato viene restituito in "radianti", per i quali probabilmente vorresti convertire e preferiresti non memorizzare un "raggio" di un cerchio con quello come misura.

Il modo in cui gestisci questo problema è, considerando i dati in questo modulo:

{
    "locationtype": "circle",
    "location": {
        "type": "Point",
        "coordinates": [1,1]
    },
    "radius": 4
}

Quindi usi .aggregate() con un $geoNear stage e un $redact per filtrare:

db.collection.aggregate([
    // Find points or objects "near" and project the distance
    { "$geoNear": {
        "near": {
            "type": "Point",
            "coordinates": [2,2]
        },
        "distanceField": "distance",
        "query": { "locationType": "circle" }
    }},
    // Logically filter anything outside of the radius
    { "$redact": {
        "$cond": {
            "if": { "$gt": [ "$distance", "$radius" ] },
            "then": "$$PRUNE",
            "else": "$$KEEP"
        }
    }}
])

Ora i valori utilizzati nell'esempio della query sono solo un esempio, ma come indicato con le coordinate di longitudine e latitudine "reali", gli attributi di "distanza" funzionano come previsto e all'interno della tolleranza "metri" come menzionato in precedenza.

I punti qui sono che $geoNear troveranno entrambi i puntini "vicino" al centro del "cerchio", indipendentemente dal tipo di oggetto. Non solo, ma il comando qui sta producendo una "proiezione" di un altro campo nel documento qui chiamato in "distanceField". Questo rappresenta la distanza dal cerchio "centro" in "metri".

La seconda fase qui usa $redact poiché è una specie di $project e $match fase dell'oleodotto in uno. A differenza di $match questo operatore può valutare una condizione "logica" confrontando i campi presenti nel documento. In questo caso, operazioni come $$PRUNE rimuovi il documento abbinato alla condizione "se" dove true e "rimuoverlo" dai risultati o in altro modo $$KEEP il documento in cui la condizione era false .

In poche parole, se "distanza" è "maggiore di" allora "raggio" del "cerchio", l'oggetto "giace fuori" del cerchio e non si "interseca". Altrimenti "lo fa".

Quindi queste sono le basi per "definire un 'cerchio' per la geometria in una raccolta e "usarlo" per ottenere qualcosa come l'intersezione tra un "Punto" o un altro tipo di Oggetto all'interno del raggio del "cerchio".