简体   繁体   中英

$geoIntersects don't work like expected

I have a question to the $geoIntersects-Operator. I have the following searchBox and collection-content:

> BOX
{
        "type" : "Polygon",
        "coordinates" : [
                [
                        [
                                0,
                                0
                        ],
                        [
                                3,
                                0
                        ],
                        [
                                3,
                                3
                        ],
                        [
                                0,
                                3
                        ],
                        [
                                0,
                                0
                        ]
                ]
        ]
}
> db.polygon.find()
{ "_id" : "Poly1", "shape" : { "type" : "Polygon", "coordinates" : [  [  [  0, 0 ],  [  3,  0 ],  [  3,  3 ],  [  0, 3 ],  [  0,  0 ] ] ] } } 
{ "_id" : "Poly2", "shape" : { "type" : "Polygon", "coordinates" : [  [  [  3, 0 ],  [  6,  0 ],  [  6,  3 ],  [  3,  3 ],  [  3,  0 ] ] ] } }
> db.polygon.find( {shape: {$geoIntersects: {$geometry: BOX}}}, {_id:1})
{ "_id" : "Poly1" }

Like you can see, the BOX and Poly1 are identical. Poly2 shared an edge with BOX. So when I was executing the $geoIntersects-Query I was expecting that both polygon's where returned because of the shared edge, but only Poly1 was found. Can somebody explain that to me? Or did I made a stupid mistake I don't see :(

Auf Wiedersehen, Andre

Good question. It looks like it's a bug or the documentation is not accurate. Just want to share the results of my small research on the issue

Point:

.find( {shape: {$geoIntersects: {$geometry: {type: "Point", coordinates : [3,0] }}}}, {_id:1})

No surprise it returns both Poly1 and Poly2.

LineString:

.find( {shape: {$geoIntersects: {$geometry: {type: "LineString", coordinates : [[3,0], [3, 3]] }}}}, {_id:1})

Returns Poly1 only, what if we revert the order of line points?

.find( {shape: {$geoIntersects: {$geometry: {type: "LineString", coordinates : [[3,3], [3, 0]] }}}}, {_id:1})

Returns Poly2 only now. So the order of the points is important for LineString which is really weird to me.

Polygon: Let's also try to change the order of points for polygon query.

.find( {shape: {$geoIntersects: {$geometry: {type: "Polygon", coordinates : [  [  [  3, 0 ],  [  3,  3 ],  [  6,  3 ],  [  6, 0 ],  [  3,  0 ] ] ]}}

Now even the order of points for line [ 3, 0 ], [ 3, 3 ] matches Poly1 definition but it still returns Poly2 only.

Summary:

So when the documentation says that

This includes documents that have a shared edge

It's no surprise true for Point, it is partially true for LineString because the order of points is important! Finnaly it's not true at all for Polygon.

This is sad in fact but really good to know. I wish I were doing something wrong during my research and would be glad if someone drop in with a good explanation.

just use smaller numbers. for triangles like these:

[{
_id:54cfbc19d9e1f418373ee427,
geo:{type:Polygon,
coordinates:[[[0.3,0.3],[0,0.3],[0,0],[0.3,0.3]]]}
},
{_id:54cfbc19d9e1f418373ee428,
geo:{type:Polygon,
coordinates:[[[0,0],[0.3,0],[0.3,0.3],[0,0]]]}
}]

.find({
    geo: {
        $geoIntersects: {
            $geometry: {
                type: "Point" ,
                coordinates: [0.005,0.005]
            }
        }
    }
})

will give you right result. I guess that $geoIntersects count that Earth is sphere.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM