At være gyldig for en "geospatial forespørgsel" "placeringen" skal være i længdegrad, breddegrad rækkefølge og kan ikke indeholde andre koordinater.
Gyldige formater er
{
"location": [long,lat]
}
Eller
{
"location": { "lng": long, "lat": lat }
}
Eller GeoJSON
{
"location": {
"type": "Point",
"coordinates": [long,lat]
}
}
Et andet felt såsom "radius" er "et andet felt" og kan ikke være en del af det samme array.
Følg helst GeoJSON:
{
"location": {
"type": "Point",
"coordinates": [long,lat]
},
"radius": radius
}
Hvilket i mongoose-skemadefinition kan være så simpelt som:
var geoSchema = new Schema({
"location": {
"type": String,
"coordinates": []
},
"radius": Number
});
Når du håndterer geospatiale data ved rigtige "globe"-koordinater, skal dit indeks være "2dsphere" , som du valgfrit definerer på skemaet som :
geoSchema.index({ "location": "2dsphere" })
Da der ikke er nogen egentlig understøttelse af et "Circle"-objekt i understøttet GeoJSON, anbefales det at beholde et andet felt som "radius" og gemme "midtpunktet".
Den "store" fordel med GeoJSON i forhold til de andre "legacy koordinatpar"-formater er, at når man returnerer noget som en "afstand" fra et punkt via geoNear
eller $geoNear
så er denne "afstand" konsekvent defineret i "meter". Det er også sådan, du skal definere enhver "radius"-værdi i dit lager for at forblive i overensstemmelse med det resultat.
Med de andre lagringsformater returneres resultatet i "radianer", som du sandsynligvis vil konvertere til og helst ikke vil gemme en "radius" af en cirkel med det som en måling.
Måden du håndterer dette på er, i betragtning af data i denne form:
{
"locationtype": "circle",
"location": {
"type": "Point",
"coordinates": [1,1]
},
"radius": 4
}
Så bruger du .aggregate()
med en $geoNear
scene og en $redact
for at filtrere:
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"
}
}}
])
Nu er de anvendte værdier i forespørgselseksemplet kun et eksempel, men som nævnt med "rigtige" længde- og breddegradskoordinater fungerer "distance"-attributterne som designet og inden for "meter"-tolerancen som nævnt tidligere.
Punkterne her er, at $geoNear
vil både finde "nær" på "cirklen" midterste poiny, uanset hvilken objekttype. Ikke kun det, men kommandoen her producerer en "projektion" af et andet felt i dokumentet her som navngivet i "distanceField". Dette repræsenterer afstanden fra cirklen "center" i "meter".
Det andet trin her bruger $redact
da det ligner et $projekt
og $match
pipeline fase i én. I modsætning til $match
denne operatør kan evaluere en "logisk" tilstand ved at sammenligne felter i dokumentet. I dette tilfælde, operationer som $$ BESKÆR
fjern det matchede dokument til "hvis"-tilstanden, hvor true
og "fjern" det fra resultater eller på anden måde $$KEEP
dokumentet, hvor betingelsen var false
.
I en "nøddeskal", hvis "afstand" er "større end" så "radius" af "cirklen", så "ligger objektet uden for" cirklen og "skærer ikke". Ellers "gør det".
Så det er det grundlæggende i "at definere en 'cirkel' for geometri i en samling og "bruge den" til at opnå noget i retning af skæringspunktet mellem et "punkt" eller en anden type objekt inden for "cirklen"-radius.