我有一个地理空间mongodb,它使用传统的坐标对作为Geo2D索引。我想从这个数据库中提取一个位置列表(传统坐标对)。对于普通列,我可以对可能的对列表使用"$in"查询,如下所示。
>>> db.collection.find_one({'country': {'$in': ['Argentina', 'Chile']}})
我不知道如何在loc列上执行此操作。loc列上的类似操作引发错误
>>> db.collection.find_one({'loc': {'$in': [(-35, 20), (-30, 21)]}})
geo field only has 1 element :: caused by :: $in: [ [ -35, 20 ], [ -30, 21 ] ]
我想到的解决方案是分别匹配列表中的每个成员。然而,这可能不是最有效的解决方案。我能做一个聚合/映射减少技巧吗?
相关信息
数据库看起来像:
>>> db.collection.find_one()
{u'value': 2.7062699269224995,
u'_id': ObjectId('56cf807e54013b935b88d3da'),
u'country': u'Algeria',
u'date': datetime.datetime(2015, 1, 1, 0, 0),
u'iso2': u'DZ',
u'lat': 27.0,
u'loc': [27.0, -8.0],
u'lon': -8.0,
u'place': u'27.0_-8.0_DZ'}
索引键为:
[ { "_id" : 1 }, { "date" : -1 }, { "loc" : "2d" } ]
这里的问题是服务器版本是MongoDB 2.4.x系列。在MongoDB 2.6.x之前,查询引擎对"地理空间"索引的处理是与标准查询分开进行的,因此,通过要求常规$in
表达式而不是$near
等地理空间操作,查询发生在引擎中无法处理表达式的部分,因为字段应用了"2d"
地理空间索引。
因此MongoDB 2.4.x"不能"使用带有常规查询操作的地理空间索引。如果您"需要"为查询使用"索引",您"必须"在查询中引用的字段上使用.ensure_index()
创建一个常规索引:
db.collection.ensure_index({ "loc": 1 })
请注意,这是对已经应用的"2d"索引的"添加"。由于索引具有不同的"类型",因此它们是单独命名和存在的。所以两者兼而有之是没有问题的。
替代方法是使用$natural
说明符将光标上的.hint()
强制执行"集合扫描",从而"忽略"地理空间索引。
从MongoDB 2.6.x及以后,查询引擎是统一的,这里的限制不适用。根据给定的查询,可能不会使用"地理空间"索引,除非您再次指定.hint()
以便显式选择要使用的索引。但它会毫无问题地工作。
最后,MongoDB 2.6.x及更高版本允许在以GeoJSON格式存储的数据上创建"地理空间"索引。即:
"location": {
"type": "Point",
"coordinates": [27.0, -8.0]
}
由于在本例中,这样的索引将在"location"
字段上,而不是直接在"location.coordinates"
数组上,因此这样的$in
查询将不会将"location"
上的"索引"识别为可用于与数组内容匹配的普通查询。在这种情况下,您将再次直接在"location.coordinates"
上创建一个普通索引,以允许查询使用该"索引"。