【问题标题】:Different semantics in $not $geoWithin with Polygon geometries between MongoDB 2.4 and 2.6$not $geoWithin 中的不同语义与 MongoDB 2.4 和 2.6 之间的多边形几何
【发布时间】:2015-04-01 10:55:20
【问题描述】:

我已经运行了以下实验,比较了 MongoDB 2.4 和 MongoDB 2.6 在 $geoWithin 选择器与 $not 与多边形(即“外部多边形”查询)的结合方面的表现。我包括了特定的版本(三个数字),我猜它与 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 索引的文档都不会在“外部多边形”查询中返回?

【问题讨论】:

    标签: mongodb


    【解决方案1】:

    2.6 的查询结果是对的——2.4 的查询结果我想我会调用不正确。从技术上讲,您的查询要求提供与$geoWithin 条件不匹配的文档。 "k" : "B" 文档与 $geoWithin 条件不匹配,因此它应该由查询返回。您可以使用$exists 删除没有p 字段的结果:

    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 应该是一个错误,但它似乎对我们有用。

    【讨论】:

    • 您是说 MongoDB 2.4 支持诸如 p: [1, 1] 之类的“普通”坐标,但 MongoDB 2.6 需要完整的 GJSON,例如 p: { type: Point, coordinates: [1, 1]}
    猜你喜欢
    • 2017-07-13
    • 1970-01-01
    • 2012-09-22
    • 1970-01-01
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 2016-06-11
    • 2010-12-19
    相关资源
    最近更新 更多