MongoDB
 sql >> Baza danych >  >> NoSQL >> MongoDB

Czy zapytania geoprzestrzenne działają na tablicach? ( $geoWithin, $geoIntersects )

Jest to jedno z tych pytań, na które należy odpowiedzieć zarówno tak, jak i nie, ponieważ tak, tablica jest obsługiwana do dopasowywania wyników, ale prawdopodobnie nie jest to to, czego naprawdę chcesz, biorąc pod uwagę ograniczenia dotyczące sposobu dopasowywania.

Godną uwagi zmianą, której potrzebujesz tutaj, jest to, że same obiekty nie są zdefiniowane w taki sposób, że MongoDB będzie je rozpoznawać w postaci, w jakiej są obecnie utworzone. Istnieją dwa indeksy i ogólne formularze wyszukiwania, które są albo ze starszymi parami współrzędnych (czyli po prostu punktami x,y) lub jako GeoJSON z obsługiwanymi obiektami GeoJSON. Twój problem polega na tym, że masz „psuedo” format GeoJSON, który tak naprawdę nie jest zgodny ze specyfikacją i próbujesz uzyskać bezpośredni dostęp do „współrzędnych”, gdzie potrzebujesz obiektu najwyższego poziomu, takiego jak:

{
    "regions": [
        {
            "name": "penta",
            "geometry": {
                "type": "Polygon",
                "coordinates": [[
                    [ 
                        -77.0322804898023610, 
                        -12.1271067552781560
                    ], 
                    [ 
                        -77.0336792618036270, 
                        -12.1255133434450870
                    ], 
                    [ 
                        -77.0326449349522590, 
                        -12.1239143495252150
                    ], 
                    [ 
                        -77.0300991833209990, 
                        -12.1238251884504540
                    ], 
                    [ 
                        -77.0299865305423740, 
                        -12.1262000752832540
                    ], 
                    [ 
                        -77.0322804898023610, 
                        -12.1271067552781560
                    ]
                ]]
            }
        },
        {
            "name": "triangle",
            "geometry": {
                "type": "Polygon",
                "coordinates": [[
                    [ 
                        -77.0313568040728570, 
                        -12.1266573492018090
                    ], 
                    [ 
                        -77.0325788855552670, 
                        -12.1246968022373030
                    ], 
                    [ 
                        -77.0300653204321860, 
                        -12.1246233756874440
                    ], 
                    [ 
                        -77.0313568040728570, 
                        -12.1266573492018090
                    ]
                ]]
            }
        }
    ]
}

W ten sposób wyodrębnia się część GeoJSON, aby była zarówno dobrze uformowana, jak i oddzielona od innych metadanych, które nie są częścią specyfikacji. Idealnie byłoby również indeksować, choć nie jest to wymagane dla $geoWithin lub $geoIntersects to z pewnością pomaga:

db.regions.createIndex({ "regions.geometry": "2dsphere" })

Definiowanie pełnej ścieżki do definicji GeoJSON w elemencie tablicy.

Wtedy zapytania działają poprawnie:

db.regions.find({
    "regions.geometry" : { 
        "$geoIntersects" : { 
            "$geometry" : { 
                "type" : "Polygon" , 
                "coordinates" : [[
                    [ -77.02877718955278 , -12.123750122669545],
                    [ -77.03457042574883 , -12.123750122669545],
                    [ -77.03457042574883 , -12.12736341792724],
                    [ -77.02877718955278 , -12.12736341792724], 
                    [ -77.02877718955278 , -12.123750122669545]
                ]]
            }
        }
    }
})

Co pasuje do powyższego dokumentu. Ale oczywiście w tablicy jest wiele obiektów, więc pytanie brzmi, który z nich pasuje? Na które nie ma obsługiwanej odpowiedzi, ponieważ MongoDB dopasowuje "dokument" i nie wskazuje w żaden sposób, który element tablicy został dopasowany.

W agregacji znajduje się opcja $geoNear to pozwala na zwrócenie dopasowanego obiektu, gdzie w tym przypadku byłby to "najbliższy". Z takimi szczegółami można następnie użyć tych informacji, aby dopasować element tablicy z pełnymi metadanymi, który zawiera element, który został znaleziony jako „najbliższy” i wyodrębnić te dane. Ale znowu jest tylko "blisko" i nigdy nie może zwrócić więcej niż jednego wyniku z tablicy.

Ale ogólnie rzecz biorąc, lepiej jest po prostu traktować oddzielne obiekty jako dokumenty we własnej kolekcji, gdzie dopasowanie do odrębnego obiektu jest tylko kwestią dopasowania dokumentu. Tak więc z powyższą tablicą w jej własnej kolekcji, po prostu wydajesz zapytanie o pasującą geometrię:

db.shapes.find({
    "geometry" : { 
        "$geoIntersects" : { 
            "$geometry" : { 
                "type" : "Polygon" , 
                "coordinates" : [ [ 
                    [ -77.02877718955278 , -12.123750122669545],
                    [ -77.03457042574883 , -12.123750122669545],
                    [ -77.03457042574883 , -12.12736341792724],
                    [ -77.02877718955278 , -12.12736341792724], 
                    [ -77.02877718955278 , -12.123750122669545]
                ]]
            }
        }
    }
})

Co daje prawidłowe obiekty, ponieważ w tym przypadku kształt przecina oba:

{
    "_id" : ObjectId("55f8d2fa66c2e7c750414b7a"),
    "name" : "penta",
    "geometry" : {
        "type" : "Polygon",
        "coordinates" : [[
            [
                    -77.03228048980236,
                    -12.127106755278156
            ],
            [
                    -77.03367926180363,
                    -12.125513343445087
            ],
            [
                    -77.03264493495226,
                    -12.123914349525215
            ],
            [
                    -77.030099183321,
                    -12.123825188450454
            ],
            [
                    -77.02998653054237,
                    -12.126200075283254
            ],
            [
                    -77.03228048980236,
                    -12.127106755278156
            ]
        ]]
    }
}
{
    "_id" : ObjectId("55f8d2fa66c2e7c750414b7b"),
    "name" : "triangle",
    "geometry" : {
        "type" : "Polygon",
        "coordinates" : [[
            [
                    -77.03135680407286,
                    -12.126657349201809
            ],
            [
                    -77.03257888555527,
                    -12.124696802237303
            ],
            [
                    -77.03006532043219,
                    -12.124623375687444
            ],
            [
                    -77.03135680407286,
                    -12.126657349201809
            ]
        ]]
    }
}

Możesz więc używać tablic, ale naprawdę możesz dopasować tylko dokument, a nie poszczególne elementy tablicy, które były częścią dopasowania, więc zwróci to oczywiście dokumenty jako całość i będziesz musiał ustalić, które elementy pasują do kryteriów w kodzie klienta .

Z drugiej strony, kilka prób zapytania ma na celu "rozbicie" tablicy współrzędnych obiektu na pojedyncze elementy. Nie jest to w ogóle obsługiwane, ponieważ obiekt może być traktowany tylko jako całość, a nie jako części „punktowe”.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. Jak zaszyfrować pole w MongoDB

  2. Przechowywać _Id jako obiekt lub ciąg w MongoDB?

  3. base64 do przewodnika do base64

  4. mongo + pasażer:właściwy sposób na ponowne połączenie z bazą danych z poziomu kolei? jak zapewnić optymalną wydajność mongo?

  5. ECS Fargate nie obsługuje montowań powiązań