För att vara giltig för en "geospatial query" "platsen" måste vara i longitud, latitud ordning och kan inte innehålla några andra koordinater.
Giltiga format är
{
"location": [long,lat]
}
Eller
{
"location": { "lng": long, "lat": lat }
}
Eller GeoJSON
{
"location": {
"type": "Point",
"coordinates": [long,lat]
}
}
Ett annat fält som "radie" är "ett annat fält" och kan inte vara en del av samma array.
Följ helst GeoJSON:
{
"location": {
"type": "Point",
"coordinates": [long,lat]
},
"radius": radius
}
Vilket i mongoose-schemadefinition kan vara så enkelt som:
var geoSchema = new Schema({
"location": {
"type": String,
"coordinates": []
},
"radius": Number
});
När du hanterar geospatiala data på verkliga "globe"-koordinater bör ditt index vara "2dsphere" , som du valfritt definierar i schemat som :
geoSchema.index({ "location": "2dsphere" })
Eftersom det inte finns något faktiskt stöd för ett "Circle"-objekt i GeoJSON som stöds, rekommenderas att behålla ett annat fält som "radie" och lagra "mittpunkten".
Den "stora" fördelen med GeoJSON jämfört med de andra "legacy koordinatpar"-formaten är att när man returnerar något som ett "avstånd" från en punkt via geoNear
eller $geoNear
då definieras det "avståndet" i "meter" konsekvent. Det är också så du bör definiera alla "radie"-värden i din lagring för att förbli konsekvent med det resultatet.
Med de andra lagringsformaten returneras resultatet i "radianer", som du förmodligen vill konvertera och föredrar att inte lagra en "radie" av en cirkel med det som ett mått.
Sättet du hanterar detta är, med tanke på data i denna form:
{
"locationtype": "circle",
"location": {
"type": "Point",
"coordinates": [1,1]
},
"radius": 4
}
Sedan använder du .aggregate()
med en $geoNear
steg och en $redact
för att filtrera:
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 är värdena som används i frågeexemplet bara ett exempel, men som nämnts med "riktiga" longitud- och latitudkoordinater fungerar "distance"-attributen som designade och inom "meters"-toleransen som nämnts tidigare.
Poängen här är att $geoNear
kommer båda att hitta "nära" "cirkeln" mittpunkten oavsett vilken objekttyp. Inte bara det utan kommandot här producerar en "projektion" av ett annat fält i dokumentet här som heter i "distanceField". Detta representerar avståndet från cirkeln "centrum" i "meter".
Det andra steget här använder $redact
eftersom det är ungefär som ett $projekt
och $match
rörledningssteg i ett. Till skillnad från $match
denna operatör kan utvärdera ett "logiskt" tillstånd genom att jämföra fält som finns i dokumentet. I det här fallet, operationer som $$ PRUNE
ta bort det matchade dokumentet till "om"-villkoret där true
och "ta bort" det från resultaten eller på annat sätt $$KEEP
dokumentet där villkoret var false
.
I ett "nötskal", om "avstånd" är "större än" då "radie" för "cirkeln" så "ligger objektet utanför" cirkeln och "korsar sig inte". Annars "gör det".
Så det är grunderna för att "definiera en "cirkel" för geometri i en samling och "använda den" för att uppnå något som liknar skärningspunkten mellan en "Punkt" eller annan typ av objekt inom "cirkelns" radie.