MongoDB - 比较模式验证器中的两个字段

问题描述 投票:0回答:1

我想为我的 MongoDB 集合创建一个查询模式验证器,如下所述: https://www.mongodb.com/docs/manual/core/schema-validation/specify-query-expression-rules/

两个示例文档可能如下所示:

{
  _id: "1",
  arr: [
    {a: 10},
    {a: 12, b: 15}
  ]
},
{
  _id: "2",
  arr: [
    {a: 12, b: 10},
    {a: 15}
  ]
}

我希望存在

arr
的所有文档仅具有满足
arr
或不具有
a > b
b
元素。在上面给出的示例中,第一个文档将无效,因为
arr
的第二个元素具有
b
并且不满足
a > b

我想到的第一个查询如下:

{
  $or: [
    {
      arr: {$exists: 0}
    },
    {
      arr: {
        $elemMatch: {
          $or: [
            {
              b: {$exists: 0}
            },
            {
              $expr: {$gt: ["$a", "$b"]}
            }
          ]
        }
      }
    }
  ]
}

可悲的是,这不起作用。显然,

$expr
不能在
$elemMatch
内部使用。

我无法使用聚合,因为模式验证器只能使用查询运算符。

$expr
里面的
$elemMatch
有什么替代品?

mongodb mongodb-query
1个回答
0
投票

以下是我对验证规则的解释:

  1. 检查
    arr
    字段
    一个。如果
    arr
    不存在,则文档通过
    b.如果
    arr
    是空数组,则文档通过
    c.如果
    arr
    包含元素,则继续步骤 2
  2. 对于arr中的
    所有
    元素,
    一个。如果元素没有字段
    b
    ,则该元素通过
    b.如果元素有字段
    b
    ,则需要
    a
    大于
    b
    才能通过

对于第 2 步,只有当所有元素都通过时文档才通过。

所以,它翻译成下面

$expr

{
  $expr: {
    $or: [
      {
        $eq: [
          0,
          {
            $size: {
              $ifNull: [
                '$arr',
                []
              ]
            }
          }
        ]
      },
      {
        $allElementsTrue: {
          $map: {
            input: '$arr',
            as: 'elem',
            'in': {
              $or: [
                {
                  $eq: [
                    null,
                    {
                      $ifNull: [
                        '$$elem.b',
                        null
                      ]
                    }
                  ]
                },
                {
                  $gt: [
                    '$$elem.a',
                    '$$elem.b'
                  ]
                }
              ]
            }
          }
        }
      }
    ]
  }
}

下面是我的本地 MongoDB 设置和示例文档的外观。可以看到文档1验证失败,文档2通过 MongoDB local setup

© www.soinside.com 2019 - 2024. All rights reserved.