MongoDB如何查询数组字段存在元素满足itv[1]-itv[0]>n的文档
MongoDB 数组内嵌字段差值匹配查询方案
现有文档结构
集合中文档的格式如下:
{ "data": [ { "itv": [0, 1], "name": "a" }, { "itv": [6, 8], "name": "b" } // 其余数组元素结构一致 ] }
查询需求
筛选出data数组中至少存在一个元素,满足itv[1] - itv[0] > n(n为指定数值阈值)的所有文档。
实现方式
MongoDB 3.6 及以上版本(推荐)
直接使用find方法,结合$elemMatch和$expr实现,语法简洁,查询性能更优:
// 把n替换为实际需要的阈值,比如阈值为2时直接写2即可 db.你的集合名.find({ data: { $elemMatch: { $expr: { $gt: [ // 计算itv[1] - itv[0]的差值 { $subtract: [ { $arrayElemAt: ["$itv", 1] }, { $arrayElemAt: ["$itv", 0] } ] }, n ] } } } })
逻辑说明:
$elemMatch负责遍历data数组的每一个元素,只要有一个元素满足后续判断条件,当前文档就会被命中$expr用于在普通查询中使用聚合表达式,支持差值计算这类运算逻辑$arrayElemAt用于按索引取出itv数组的对应位置元素,$subtract计算两个元素的差值,最后通过$gt判断差值是否大于阈值
MongoDB 3.6 以下版本
低版本不支持在$elemMatch中使用$expr,可以通过聚合管道实现相同逻辑:
db.你的集合名.aggregate([ { $match: { $expr: { $anyElementTrue: { $map: { input: "$data", as: "dataItem", in: { $gt: [ { $subtract: [ { $arrayElemAt: ["$$dataItem.itv", 1] }, { $arrayElemAt: ["$$dataItem.itv", 0] } ] }, n ] } } } } } } ])
逻辑说明:
$map会遍历data数组的所有元素,逐元素计算itv差值和阈值的比较结果,返回布尔值组成的数组$anyElementTrue判断上述布尔值数组中是否存在true,存在则当前文档符合匹配要求
验证示例
针对给出的示例文档:
- 当阈值n=1时,b元素的itv差值为
8-6=2>1,文档会被匹配 - 当阈值n=2时,所有元素的itv差值最大为2,不满足大于2的条件,文档不会被匹配
内容的提问来源于stack exchange,提问作者Quang Lê
相关产品推荐
相关产品推荐

