Aby mieć prawo do "zapytania geoprzestrzennego" „lokalizacja” musi znajdować się w długości i szerokości geograficznej zamówienia i nie może zawierać żadnych innych współrzędnych.
Prawidłowe formaty to
{
"location": [long,lat]
}
Lub
{
"location": { "lng": long, "lat": lat }
}
Lub GeoJSON
{
"location": {
"type": "Point",
"coordinates": [long,lat]
}
}
Inne pole, takie jak „promień”, to „inne pole” i nie może być częścią tej samej tablicy.
Najlepiej postępuj zgodnie z GeoJSON:
{
"location": {
"type": "Point",
"coordinates": [long,lat]
},
"radius": radius
}
Który w definicji schematu mangusty może być tak prosty jak:
var geoSchema = new Schema({
"location": {
"type": String,
"coordinates": []
},
"radius": Number
});
W przypadku danych geoprzestrzennych w rzeczywistych współrzędnych „globu” indeks powinien mieć postać "2dsphere" , który opcjonalnie można zdefiniować w schemacie jako :
geoSchema.index({ "location": "2dsphere" })
Ponieważ w obsługiwanym GeoJSON nie ma rzeczywistej obsługi obiektu „Okrąg”, zalecane jest utrzymywanie innego pola jako „promień” i przechowywanie „punktu centralnego”.
„Dużą” przewagą GeoJSON nad innymi „starymi parami współrzędnych” jest zwracanie czegoś takiego jak „odległość” od punktu przez geoNear
lub $geoNear
wtedy ta „odległość” jest konsekwentnie definiowana w „metrach”. W ten sposób powinieneś również definiować dowolną wartość „promienia” w swojej pamięci, aby zachować spójność z tym wynikiem.
W przypadku innych formatów przechowywania wynik jest zwracany w „radianach”, dla których prawdopodobnie chcesz przekonwertować i nie chcesz przechowywać „promienia” okręgu jako miary.
Sposób, w jaki sobie z tym radzisz, to uwzględnienie danych w tej formie:
{
"locationtype": "circle",
"location": {
"type": "Point",
"coordinates": [1,1]
},
"radius": 4
}
Następnie używasz .aggregate()
z $geoNear
etap i $redact
filtrować:
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"
}
}}
])
Teraz wartości użyte w przykładzie zapytania są tylko przykładem, ale jak stwierdzono w przypadku „rzeczywistych” współrzędnych długości i szerokości geograficznej, atrybuty „odległość” działają zgodnie z założeniami i mieszczą się w tolerancji „metrów”, jak wspomniano wcześniej.
Chodzi o to, że $geoNear
oboje znajdą "blisko" do "koła" środkowego poiny, bez względu na typ obiektu. Nie tylko to, ale polecenie tutaj tworzy "rzut" innego pola w dokumencie tutaj, jak nazwano w "distanceField". Przedstawia odległość od „środka” okręgu w „metrach”.
Drugi etap tutaj używa $redact
ponieważ jest to trochę jak $projekt
i $match
etap rurociągu w jednym. W przeciwieństwie do $match
ten operator może ocenić „logiczny” warunek, porównując pola obecne w dokumencie. W tym przypadku operacje takie jak $$ PRZYCIĄĆ
usuń dopasowany dokument do warunku „if”, gdzie prawda
i „usuń” go z wyników lub w inny sposób ZACHOWAJ $$
dokument, w którym warunek był fałsz
.
Krótko mówiąc, jeśli odległość jest większa niż promień okręgu, obiekt leży na zewnątrz okręgu i nie przecina się. W przeciwnym razie „tak”.
To są podstawy „definiowania „okręgu” geometrii w kolekcji i „używania go”, aby osiągnąć coś w rodzaju przecięcia „punktu” lub innego typu obiektu w promieniu „okręgu”.