MongoDB子文档的嵌套文档验证 [英] MongoDB nested Document Validation for sub-documents

查看:65
本文介绍了MongoDB子文档的嵌套文档验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我得到了一个结构如下的文档.我的问题是如何在数据库端进行嵌套部分的角色"验证.我的要求是:

  • 角色大小可以为0或大于1.
  • 如果创建了角色,则存在角色的名称和created_by.

    {
      "_id": "123456",
      "name": "User Name",
      "roles": [
        {
          "name": "mobiles_user",
           "last_usage_at": {
             "$date": 1457000592991
            },
            "created_by": "987654",
            "created_at": {
              "$date": 1457000592991
            }
        },
        {
          "name": "webs_user",
           "last_usage_at": {
             "$date": 1457000592991
            },
            "created_by": "987654",
            "created_at": {
              "$date": 1457000592991
            }
        },
      ]
    }
    

目前,我仅对那些没有嵌套的属性执行以下操作:

db.createCollection( "users",
   { "validator" : {
     "_id" : {
         "$type" : "string"
      },
      "email" : {
         "$regex" : /@gmail\.com$/
      },
      "name" : {
         "$type" : "string"
      }
   }
} )

任何人都可以建议如何进行嵌套文档验证吗?

解决方案

编辑:此答案不正确,有可能 验证阵列中的所有子文档.查看答案: https://stackoverflow.com/a/43102783/200224

你不能真的.您可以执行以下操作:

 "roles.name": { "$type": "string" }
 

但是真正的意思是这些属性中的至少一个"需要与指定的类型匹配.这意味着这实际上是有效的:

 {
    "_id" : "123456",
    "name" : "User Name",
    "roles" : [
            {
                    "name" : "mobiles_user",
                    "last_usage_at" : ISODate("2016-03-03T10:23:12.991Z"),
                    "created_by" : "987654",
                    "created_at" : ISODate("2016-03-03T10:23:12.991Z")
            },
            {
                    "name" : "webs_user",
                    "last_usage_at" : ISODate("2016-03-03T10:23:12.991Z"),
                    "created_by" : "987654",
                    "created_at" : ISODate("2016-03-03T10:23:12.991Z")
            },
            {
                    "name" : 1
            }
    ]
}
 

毕竟是文档验证" ,这是天生的不太适合数组中的子文档,或者不适合包含在数组中的任何数据.

实现的核心依赖于查询运算符可用的表达式,并且由于MongoDB在标准查询表达式中缺少等同于所有数组条目必须匹配此值" 的任何内容,而没有直接指定,因此无法表示为验证器条件. >

检查查询"表达式中的数组内容的唯一可能性是使用 $where ,并且该文档在文档验证中不是可用的选项.

即使 $size 运算符也可用于查询必须匹配特定的大小"值,并且不能使用不等式条件.因此,您可以验证"一个严格的尺寸,但不能验证最小尺寸,除非:

 "roles.0": { "$exists": true }
 

这是婴儿期"中的一项功能,有些实验性,因此将来的发行版可能会解决此问题.

但是现在,您最好的选择是在客户端代码中进行这种模式验证"(在该代码中,您将获得更好的异常报告).已经有许多采用这种方法的库.

I got a document structured like the following. My question is how do I do the nested part "roles" validation on the database side. My requirements are:

  • the roles size could be 0 or more than 1.
  • the presence of name and created_by for a role if a role is created.

    {
      "_id": "123456",
      "name": "User Name",
      "roles": [
        {
          "name": "mobiles_user",
           "last_usage_at": {
             "$date": 1457000592991
            },
            "created_by": "987654",
            "created_at": {
              "$date": 1457000592991
            }
        },
        {
          "name": "webs_user",
           "last_usage_at": {
             "$date": 1457000592991
            },
            "created_by": "987654",
            "created_at": {
              "$date": 1457000592991
            }
        },
      ]
    }
    

At the moment, I am only doing the following for those none nested attributes:

db.createCollection( "users",
   { "validator" : {
     "_id" : {
         "$type" : "string"
      },
      "email" : {
         "$regex" : /@gmail\.com$/
      },
      "name" : {
         "$type" : "string"
      }
   }
} )

Could anyone please advise that how to do the nested document validation?

解决方案

Edit: this answer is not correct, it is possible to validate all sub-documents in the array. See answer: https://stackoverflow.com/a/43102783/200224

You can't really. You can do things like:

"roles.name": { "$type": "string" }

But all that really means is at "at least one" of those properties need match the specified type. That means this would actually be valid:

{
    "_id" : "123456",
    "name" : "User Name",
    "roles" : [
            {
                    "name" : "mobiles_user",
                    "last_usage_at" : ISODate("2016-03-03T10:23:12.991Z"),
                    "created_by" : "987654",
                    "created_at" : ISODate("2016-03-03T10:23:12.991Z")
            },
            {
                    "name" : "webs_user",
                    "last_usage_at" : ISODate("2016-03-03T10:23:12.991Z"),
                    "created_by" : "987654",
                    "created_at" : ISODate("2016-03-03T10:23:12.991Z")
            },
            {
                    "name" : 1
            }
    ]
}

It is afterall "documement validation" and that is by nature not well suited to sub-documents in arrays, or any data in a contained array really.

The core of the implementation relies on expressions available to query operators, and since MongoDB lacks anythin in standard query expressions that equates to "All array entries must match this value" without being directly specific then it's not possible to express as a validator condition.

The only posibility to check array content like that in a "query" expression is using $where, and that is noted to not be an available option with document validation.

Even the $size operator available for queries must match a specific "size" value, and cannot use an in-equality condition. So you "could" verify a strict size, but not a minimal size, unless:

"roles.0": { "$exists": true }

This is a feature in "infancy" and somewhat experimental, so there is the possibility that future releases may address this.

But for now, your better option is to do such "schema validation" in client side code ( where you will get a lot better exception reporting ) instead. There are many libraries already existing that take that approach.

这篇关于MongoDB子文档的嵌套文档验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆