Mongodb查找比较数组元素
Posted
技术标签:
【中文标题】Mongodb查找比较数组元素【英文标题】:Mongodb find comparing array elements 【发布时间】:2013-11-23 17:07:18 【问题描述】:我有一个包含大约 200K 文档的集合:
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
有什么提示吗? 提前致谢
【问题讨论】:
应该是:db.place.find('center.0':'$gt':'center.1').count()
注意 center.1 周围的引号
我试过这个查询,但似乎不起作用。我使用的是 2.4.7 版本。我用 $where 运算符代替了答案。
你不能引用 where 右边的文档内容(即 a:1 可以,a:b 其中 b 是另一个字段是不行的。如果你需要比较 x 和 y,您可能会认为该架构不适合您的用例 - 您是否必须像这样存储 x 和 y?
可能有一种方法可以在不使用 $where 的情况下做到这一点。 “中心”总是一个包含两个元素的数组,还是它可能有更多或更少的元素? “x”和“y”的类型是什么——它们是数字吗?
大家好,感谢您的回复...事实上 '$gt':'center.1' 的解决方案返回 0,因为它比较浮点数和字符串..
【参考方案1】:
因为你碰巧每次都有精确的字段格式(圆圈是一个二元素数组),你可以在聚合框架中将它转换为两个字段,然后在投影中比较它们,并匹配以获取满足的元素您对第二个数组元素的要求大于第一个数组元素。
db.place.aggregate( [
$unwind : "$center" ,
$group : _id : "$_id",
centerX : $first:"$center",
centerY : $last:"$center"
,
$project : YgtX : $gt : [ "$centerY", "$centerX" ] ,
$match : YgtX : true
] );
现在,如果您的数组是任意一对数值,那么您可以使用上面的。
您在 cmets 中说过您的坐标对表示坐标(纬度、经度) - 请记住,在 MongoDB 中坐标对始终为 stored as long, lat - 如果您的实际 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】:看来您需要改用$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 ]
【讨论】:
您好 Victoria,感谢您的回复。正如 Salvador Dali 所说,这不是一个高性能的解决方案...将继续寻找更快的方法。【参考方案3】:你不能在 mongo 中以简单的方式进行你想要的查询,因为 mongo 不支持基于集合中的元素进行搜索或更新。所以即使像a : 1, b : 1
这样简单的文档,如果没有$where
子句,也可以找到a = b 不可能的文档。
idbentley db.place.find('center.0':'$gt':'center.1')
建议的解决方案将无法正常工作(也不会产生错误),因为这样您会将 center.0 与字符串 'center.1' 进行比较。因此正确的解决方案是 Victoria Malaya 的解决方案(但她忘了把 .count() 放在最后)。
我想建议一件事。任何带有 where 的东西都非常非常慢。因此,如果您打算多次执行此查询,请考虑创建额外的字段来存储此预先计算的结果(您可以使用this 答案以类似的方式执行此操作)。
【讨论】:
【参考方案4】:您也可以使用$expr
运算符:https://docs.mongodb.com/manual/reference/operator/query/expr/
db.place.find($expr: $gt: ['$center.0', '$center.1']).count()
但是:类似于$where
$expr
非常慢,详细阅读这里:Mongodb $expr query is very slow
此处示例:https://medium.com/@deepakjoseph08/mongodb-query-expressions-that-compare-fields-from-the-same-document-ccb45a1f064b
【讨论】:
以上是关于Mongodb查找比较数组元素的主要内容,如果未能解决你的问题,请参考以下文章