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:查询嵌套数组的大小的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB:如何查询嵌套数组?

在 MongoDb 中查询嵌套数组

MongoDB 嵌套对象数组后查询

MongoDB 嵌套对象数组后查询

MongoDB - 查询计算数组中的嵌套文档

带有 elemMatch 的 MongoDB 查询,用于从对象内部匹配嵌套数组数据 [重复]