Mongodb:查询嵌套数组的大小
Posted
技术标签:
【中文标题】Mongodb:查询嵌套数组的大小【英文标题】:Mongodb: Query the size of nested arrays 【发布时间】:2022-01-02 07:54:01 【问题描述】:我有以下架构:
Schema(
caller_address:
type: String,
required: true,
,
traces: [[
type: mongoose.Schema.Types.ObjectId,
ref: 'Call',
]]
);
我想只检索具有呼叫量大于指定数字的跟踪的对象。换句话说,至少一个嵌套的轨迹数组的大小应该大于指定的数字。 我正在尝试使用 $elemMatch 和 $size,但没有成功。现在,我有这个代码:
CallerTraces.find( 'traces' : $elemMatch: $size : $gt: minTraceSize )
其中 minTraceSize 是一个 int。
你们能帮帮我吗? 我真的很感激!
【问题讨论】:
您能提供示例 JSON 数据吗? 一个简单的数据实例: "_id": "$oid": "6175e7ecc62cff004462d4a6" , "traces": [ [ "$oid": "6175e7ecc62cff004462d4a4" ] ], "caller_address ": "0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990" 例如,如果我将 minTraceSize 设置为 1,这应该返回。 还有这个: "_id": "$oid": "6175e7ecc62cff004462d4a6" , "traces": [ [ "$oid": "6175e7ecc62cff004462d4a4" , "$oid": "6175e7ecc62cff004462d4a4" ], [ "$oid": "6175e7ecc62cff004462d4a4" ] ], "caller_address": "0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990" 如果我将 minTraceSize 设置为 2。 【参考方案1】:感谢您提供示例数据。我的答案将是原始 MQL 解决方案,而不是猫鼬解决方案,因此需要进行一些翻译。
我能够在您的帖子中根据您的 cmets 插入两个文档。我不得不更改两个示例文档之一的 ObjectId,因为您的示例具有相同的主键值并且正在生成重复键异常。
插入样本数据
db.CallerTraces.insert(
"_id": ObjectId("6175e7ecc62cff004462d4a6"),
"traces": [
[
ObjectId("6175e7ecc62cff004462d4a4")
]
],
"caller_address": "0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990"
)
db.CallerTraces.insert(
"_id": ObjectId("6175e7ecc62cff004462d4a7"),
"traces": [
[
ObjectId("6175e7ecc62cff004462d4a4"),
ObjectId("6175e7ecc62cff004462d4a4")
],
[
ObjectId("6175e7ecc62cff004462d4a4")
]
],
"caller_address": "0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990"
)
如果我想在数组 traces
中查找超过 0 个项目的记录,我可以发出以下命令:
发现不止零的痕迹
db.CallerTraces.find( $expr: $gt: [ $size: "$traces" , 0 ] )
这将返回以下内容:
Enterprise replSet [primary] barrydb> db.CallerTraces.find( $expr: $gt: [ $size: "$traces" , 0 ] )
[
_id: ObjectId("6175e7ecc62cff004462d4a6"),
traces: [ [ ObjectId("6175e7ecc62cff004462d4a4") ] ],
caller_address: '0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990'
,
_id: ObjectId("6175e7ecc62cff004462d4a7"),
traces: [
[
ObjectId("6175e7ecc62cff004462d4a4"),
ObjectId("6175e7ecc62cff004462d4a4")
],
[ ObjectId("6175e7ecc62cff004462d4a4") ]
],
caller_address: '0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990'
]
查找超过 1 条轨迹
如果我想查找多个跟踪,我只需稍微更改查询:
db.CallerTraces.find( $expr: $gt: [ $size: "$traces" , 1 ] )
...这将返回以下结果:
Enterprise replSet [primary] barrydb> db.CallerTraces.find( $expr: $gt: [ $size: "$traces" , 1 ] )
[
_id: ObjectId("6175e7ecc62cff004462d4a7"),
traces: [
[
ObjectId("6175e7ecc62cff004462d4a4"),
ObjectId("6175e7ecc62cff004462d4a4")
],
[ ObjectId("6175e7ecc62cff004462d4a4") ]
],
caller_address: '0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990'
]
结论
当尝试在查询处理器中评估数组的长度时,我们必须选择使用 $eval
选项,因为 MQL 的语法不考虑您的用例。 $eval
对于不能很好地融入 MQL 框架的事物来说,在某种程度上是一个包罗万象的选项。
更新 #1
OP 引入了额外的要求。而不是看数组的计数,我们必须考虑数组内数组的计数(嵌套内部数组)。由于带有 $expr 的 find() 方法无法评估嵌套数组,我们必须改为使用聚合框架并展开外部数组。此示例将原始表单存储在名为 original
的新字段中,然后在所有评估完成后替换 root。由于展开可能会导致管道中出现重复,因此我们使用 $group 来终止重复。
解决方案
db.CallerTraces.aggregate([
$addFields:
"original._id": "$_id",
"original.traces": "$traces",
"original.caller_address": "$caller_address"
,
$unwind: "$traces"
,
$match: $expr: $gt: [ $size: "$traces" , 1 ]
,
$replaceRoot: newRoot: "$original"
,
$group:
_id: "$_id",
traces: "$first": "$traces" ,
caller_address: "$first": "$caller_address"
])
【讨论】:
您好,感谢您的快速回复!但还不是问题...我想在第二级嵌套中获得 Traces 大小。所以,如果我有: “_id”:物件( “6175e7ecc62cff004462d4a7”), “痕迹”:[的ObjectId( “6175e7ecc62cff004462d4a4”)的ObjectId( “6175e7ecc62cff004462d4a4”)], “caller_address”: “0x4e204793bc4b8acee32edaf1fbba1f3ea45f7990”)这当我将 2 设置为 minTraceSize 变量时,对象应该返回。 @BrunoMedeiros - 请在我的帖子中查看更新。 成功了!太感谢了! =)以上是关于Mongodb:查询嵌套数组的大小的主要内容,如果未能解决你的问题,请参考以下文章