Geldig zijn voor een "geospatial query" de "locatie" moet in lengtegraad, breedtegraad . zijn bestelling en mag geen andere coördinaten bevatten.
Geldige formaten zijn
{
"location": [long,lat]
}
Of
{
"location": { "lng": long, "lat": lat }
}
Of GeoJSON
{
"location": {
"type": "Point",
"coordinates": [long,lat]
}
}
Een ander veld zoals "radius" is "another field" en kan niet deel uitmaken van dezelfde array.
Volg idealiter GeoJSON:
{
"location": {
"type": "Point",
"coordinates": [long,lat]
},
"radius": radius
}
Wat in de definitie van een mangoestschema zo simpel kan zijn als:
var geoSchema = new Schema({
"location": {
"type": String,
"coordinates": []
},
"radius": Number
});
Als je te maken hebt met geospatiale gegevens op echte "globe"-coördinaten, moet je index "2dsphere" , die u optioneel in het schema definieert als :
geoSchema.index({ "location": "2dsphere" })
Aangezien er geen daadwerkelijke ondersteuning is voor een "Circle"-object in ondersteunde GeoJSON, wordt aanbevolen om een ander veld als "radius" te behouden en het "middelpunt" op te slaan.
Het "grote" voordeel met GeoJSON ten opzichte van de andere "oude coördinatenparen"-formaten is dat bij het retourneren van iets als een "afstand" vanaf een punt via geoNear
of $geoNear
dan wordt die "afstand" consequent gedefinieerd in "meters". Dit is ook hoe u elke "radius" -waarde in uw opslag moet definiëren om consistent te blijven met dat resultaat.
Bij de andere opslagformaten wordt het resultaat geretourneerd in "radialen", waarvoor u waarschijnlijk wilt converteren en liever geen "radius" van een cirkel met die als maat opslaat.
De manier waarop u hiermee omgaat is, rekening houdend met gegevens in deze vorm:
{
"locationtype": "circle",
"location": {
"type": "Point",
"coordinates": [1,1]
},
"radius": 4
}
Dan gebruik je .aggregate()
met een $geoNear
stage en een $redact
om te filteren:
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 zijn de waarden die in het queryvoorbeeld worden gebruikt slechts een voorbeeld, maar zoals vermeld met "echte" lengte- en breedtegraadcoördinaten werken de "afstand"-attributen zoals ontworpen en binnen de "meters"-tolerantie zoals eerder vermeld.
De punten hier zijn dat $geoNear
zullen beide "dichtbij" bij het middelpunt van de "cirkel" vinden, ongeacht het objecttype. Niet alleen dat, maar de opdracht hier produceert een "projectie" van een ander veld in het document hier zoals genoemd in "distanceField". Dit vertegenwoordigt de afstand van de cirkel "middelpunt" in "meters".
De tweede fase hier gebruikt $redact
aangezien het een soort $project
en $match
pijplijntrap in één. In tegenstelling tot $match
deze operator kan een "logische" voorwaarde evalueren door velden in het document te vergelijken. In dit geval zijn bewerkingen zoals $$ snoeien
verwijder het overeenkomende document naar de "if"-voorwaarde waarbij true
en "verwijder" het uit resultaten of anderszins $$KEEP
het document waar de voorwaarde false
was .
In een "notendop", als "afstand" "groter dan" is, dan "straal" van de "cirkel", dan "ligt" het object "buiten" van de cirkel en "kruist" het niet. Anders "doet het dat wel".
Dat is dus de basis van het "definiëren van een 'cirkel' voor geometrie in een verzameling en 'gebruiken' om zoiets te bereiken als de kruising tussen een 'punt' of een ander type object binnen de 'cirkel'-straal.