有没有办法在嵌入式文档中查询嵌入文档?

时间:2015-08-23 09:49:36

标签: mongodb mongodb-query aggregation-framework

我有一个奇怪的mongodb文档,但仍然需要查询它。有可能吗?

例如:我需要一定范围内的每个玩家。

{
    "_id" : ObjectId("55d89c63c746230c200c528e"),
    "speler_id" : 12,
    "naam" : "Arjen Robben",
    "seconds" : [ 
        [ 
            {
                "locatie" : [ 
                    8.7173307286181370, 
                    33.2784843816214250
                ],
                "timestamp" : ISODate("1970-01-01T19:00:01.000Z")
            }, 
            {
                "locatie" : [ 
                    -45.8853075448968970, 
                    138.1526615469845800
                ],
                "timestamp" : ISODate("1970-01-01T19:00:02.000Z")
            }, 
            {
                "locatie" : [ 
                    80.5503710377444690, 
                    10.0500048843973580
                ],
                "timestamp" : ISODate("1970-01-01T19:00:03.000Z")
            }
        ]
    ]
}

1 个答案:

答案 0 :(得分:0)

您可以随$geoWithin$center使用$centerSphere(取决于这些是全局几何坐标还是仅用于平面,以便进行距离校准),然后使用{{进行处理3}}在聚合框架中:

db.collection.aggregate([
    { "$unwind": "$seconds" },
    { "$unwind": "$seconds" },
    { "$match": {
        "seconds.locatie": {
            "$geoWithin": {
                "$centerSphere": [
                    [ 
                       8.7173307286181370, 
                        33.2784843816214250
                    ],
                    100
                ]
            }
        }
    }}
])

所呈现的数据将返回:

{
    "_id" : ObjectId("55d89c63c746230c200c528e"),
    "speler_id" : 12,
    "naam" : "Arjen Robben",
    "seconds" : {
        "locatie" : [
                8.717330728618137,
                33.278484381621425
        ],
        "timestamp" : ISODate("1970-01-01T19:00:01Z")
    }
}
{
    "_id" : ObjectId("55d89c63c746230c200c528e"),
    "speler_id" : 12,
    "naam" : "Arjen Robben",
    "seconds" : {
        "locatie" : [
                80.55037103774447,
                10.050004884397358
        ],
        "timestamp" : ISODate("1970-01-01T19:00:03Z")
    }
}

由于$geoWithin不“需要”地理空间索引,因此可以在以后的聚合阶段使用,而不是初始匹配。在这种情况下,$centerSphere定义了一个要查询的点和从该点延伸的“半径”。这只是一个几何“快捷方式”,因为您可以交替提供您自己定义的GeoJSON多边形。

但它并不是很棒。而且主要是因为它无法使用索引,因此对整个集合来说几乎是一种蛮力,并且你不能做很好的事情,例如返回查询点的距离,就像你可以用{{3}做的那样}。

因此,虽然您可以执行此类操作,但使用MongoDB的大多数地理空间查询最好留下将位置数据保留在文档的顶层,而不是嵌入到数组中。因此,这种建模通常意味着拥有单独的集合对象而不是嵌入集合对象,以获得最佳结果。

如果您希望在响应中使用聚合数组,那么在进行初始地理空间查询后,最好在聚合中执行此操作。