MongoDB查找比较数组元素

3

我是一个有用的助手,可以为您翻译文本。

我有一个包含约20万个文档的集合,格式如下:

db.place.find()[0]
{
    "_id" : ObjectId("5290de1111afb260363aa4a1"),
    "name" : "place X",
    "center" : [x, y]   
}

现在我正在尝试查询中心Y大于X的地点,并遇到以下问题:

> db.place.find({'center.0':{'$gt':center.1}}).count()
Sat Nov 23 14:42:01.556 JavaScript execution failed: SyntaxError: Unexpected number

任何提示? 提前感谢。

2
db.place.find({'center.0':{'$gt':'center.1'}}).count() 应注意引号包围着 center.1。 - idbentley
我尝试了这个查询,但似乎它不起作用。我正在使用2.4.7版本。我已经改用$where运算符回答了。 - Victoria Malaya
你不能参考右侧文档的内容来解释(例如 {a:1} 是可以的,但 {a:b} 中 b 是另一个字段就不行)。如果你需要比较 x 和 y,你可能需要考虑一下这个模式是否适合你的使用情况 - 你必须像这样存储 x 和 y 吗? - Asya Kamsky
可能有一种方法可以不使用 $where 来实现这个。"center" 是否总是一个具有两个元素的数组,或者它可能具有更多或更少的元素?而 "x" 和 "y" 的类型是什么 - 它们是数字吗? - Asya Kamsky
哇...刚刚查看了有关经度纬度的文档,发现使用的是lon lat而不是lat lon...在巴西我们使用第二种形式,并且所有的数据库都是这样的。问题出现在我们以正确的方式(我认为是错误的格式)加载标记数据集时...无论如何,我将尝试您的聚合解决方案来修复它,对我来说这是一个解决方案,因为我确信我的经度小于纬度。 - André Teixeira
显示剩余4条评论
4个回答

4

看起来您需要使用$where操作符。

db.place.find({$where: function() {return this.center[0] > this.center[1]}})

例如,集合中有3个文档:
{ "_id" : ObjectId("52910457c7d99f10949e5a85"), "name" : "place X", "center" : [ 2,  3 ] }
{ "_id" : ObjectId("52910463c7d99f10949e5a86"), "name" : "place Y", "center" : [ 3,  2 ] }
{ "_id" : ObjectId("5291046ac7d99f10949e5a87"), "name" : "place Y", "center" : [ 8,  9 ] }
$where 命令的结果将是:
{ "_id" : ObjectId("52910463c7d99f10949e5a86"), "name" : "place Y", "center" : [ 3,  2 ] }

1
你好Victoria,感谢回复。正如Salvador Dali所说,这不是一个高效的解决方案... 我会继续寻找更快的方法。 - André Teixeira

4

因为每次字段的格式都是一样的(circle是一个包含两个元素的数组),所以您可以在聚合框架中将其转换为两个字段,然后在投影中进行比较,并匹配以仅获取满足第二个数组元素大于第一个数组元素要求的元素。

db.place.aggregate( [
      { $unwind : "$center" },
      { $group : { _id : "$_id", 
                   centerX : {$first:"$center"}, 
                   centerY : {$last:"$center"} 
      } },
      { $project : { YgtX : { $gt : [ "$centerY", "$centerX" ] } } },
      { $match : { YgtX : true } }
] );

现在,如果您的数组是任意一对数值,那么您可以使用上述方法。
您在评论中说,您的一对值代表了坐标(纬度,经度)-请记住,在MongoDB中,坐标对始终存储为经度,纬度-如果您的实际x,y值是平面空间上的坐标(而不是球体),您可以使用单个地理空间查询找到所有Y坐标大于X坐标的文档:
db.place.find( { center : { $geoWithin : { $geometry : {
                  type:"Polygon", 
                  coordinates:[[[50,50],[-50,50],[-50,-50],[50,50]]]
} } } } );

上述查询假定您的坐标系沿X和Y从-50到50,它查找表示所有具有Y>=X的坐标的三角形中的所有点。

2
在Mongo中,您无法通过集合元素进行搜索或更新,因此无法以简单的方式执行所需的查询。因此,即使是像{a:1,b:1}这样简单的文档,也无法查找其中a = b的文档,除非使用$where子句。
idbentley提出的解决方案db.place.find({'center.0':{'$gt':'center.1'}})也不起作用(也不会生成错误),因为这种方法将center.0与字符串'center.1'进行比较。因此正确的解决方案是Victoria Malaya的解决方案(但她忘记在结尾处加上.count())。
我想建议一件事情。任何带有where的内容都非常缓慢。因此,如果您计划执行此查询超过一次,请考虑创建额外的字段来存储预先计算的结果(您可以按照此答案的方式执行)。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接