我运行了以下实验,比较了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”查询中返回?
答案 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应该是错误,但它似乎对我们有用。