使用MongoDB 2.4和2.6之间的多边形几何的$ not $ geoWithin中的不同语义

时间:2015-04-01 10:55:20

标签: mongodb

我运行了以下实验,比较了MongoDB 2.4和MongoDB 2.6在$geoWithin选择器与$not结合多边形(即“外部多边形”查询)方面的行为。我包括了特定的版本(三个数字),alghouth我想它会与2.4和2.6的其他次要版本一样。

在给定集合中创建两个文档(A和B):A p字段设置为坐标[1,1],B没有p字段。接下来,我在p中创建一个2dsphere索引,并对三角形外的区域进行查询,其中顶点为[0,0],[0,4]和[4,0]。注意A是里面那个多边形(因此不应该使用此查询)。

用2.4.9:

db.x.insert({k: "A", p: [1,1]})
db.x.insert({k: "B"})
db.x.ensureIndex({"p": "2dsphere"})
db.x.find({p: { $not: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [ [ [ 0, 0 ], [ 0, 4 ], [ 4, 0 ], [ 0, 0 ] ] ] } } } }})
--> no result

有道理:A不会返回(因为它在多边形内)并且不返回B(假设它没有p字段)。

接下来,使用2.6.1测试相同的脚本:

db.x.insert({k: "A", p: [1,1]})
db.x.insert({k: "B"})
db.x.ensureIndex({"p": "2dsphere"})
db.x.find({p: { $not: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [ [ [ 0, 0 ], [ 0, 4 ], [ 4, 0 ], [ 0, 0 ] ] ] } } } }})   
-> result: B

似乎在2.6语义中已经改变了,所以当2dsphere-indexed字段不在给定文档中时,该文档被认为是在任何可能的多边形之外。

只要新版本中的某些机制允许以旧方式配置行为,就可以更改版本之间的语义。我认为该机制在索引创建时使用{ "2dsphereIndexVersion" : 1 }(基于我读到的here,也许我误解了这些信息......)。但是,结果(再次使用2.6.1)是相同的:

db.x.insert({k: "A", p: [1,1]})
db.x.insert({k: "B"})
db.x.ensureIndex({"p": "2dsphere"}, { "2dsphereIndexVersion" : 1 })
db.x.find({p: { $not: { $geoWithin: { $geometry: { type: "Polygon", coordinates: [ [ [ 0, 0 ], [ 0, 4 ], [ 4, 0 ], [ 0, 0 ] ] ] } } } }})
-> result B

因此,有没有任何方法可以使用MongoDB 2.6与MongoDB 2.4相同的语义,即没有2dsphere-indexed的任何文档都不会在“外部poylgon”查询中返回?

1 个答案:

答案 0 :(得分:3)

2.6中的查询结果是正确的 - 2.4中的查询结果我认为我会调用不正确。从技术上讲,您的查询会询问与$geoWithin条件不匹配的文档。 "k" : "B"文档与$geoWithin条件不匹配,因此查询应返回该文档。您可以使用p

删除没有$exists字段的结果
db.x.find({
    "p" : { 
        "$exists" : true, 
        "$not" : { "$geoWithin" : { 
            "$geometry" : { 
                "type": "Polygon", 
                "coordinates" : [ [ [ 0, 0 ], [ 0, 4 ], [ 4, 0 ], [ 0, 0 ] ] ] 
            } 
    } } }
})

另请注意:1)您的$not查询实际上并未使用地理索引,因为您可以查看解释,2)使用2dsphere索引时,您应该将点存储为GeoJSON

{ 
    "k" : "A", 
    "p" : {
        "type" : "Point",
        "coordinates" : [1,1]
    }
}

从技术上讲,MongoDB中需要> = 2.6,并且文档说不使用GeoJSON应该是错误,但它似乎对我们有用。