简体   繁体   English

验证mongodb中的嵌入式文档

[英]Validate embedded document in mongodb

I'd like to validate my documents in MongoDB. 我想在MongoDB中验证我的文档。 As described here , the validator query can be specified during the createCollection command. 如所描述的在这里 ,可以在过程中指定的验证查询createCollection命令。

My application is a simple todo list, so the collection list has many documents like this: 我的应用程序是一个简单的待办事项列表,因此收集list包含许多这样的文档:

{
   "name": "the list name",
   "color: "red",
   "items": [
     {
       "title": "item1",
       "isDone": false,
       "text": "the item description"
     }
   ]
} 

How can I sure that all documents has this shape? 如何确定所有文档都具有这种形状?

EDIT: I'm using MongoDB 3.4 编辑:我正在使用MongoDB 3.4

You can't. 你不能

There's no way to avoid new property. 没有避免新财产的方法。 If this needed is required, you should consider to migrate a SQL solution. 如果需要此要求,则应考虑迁移SQL解决方案。

Otherwise, your document will contain at least those members and those members will be validated. 否则,您的文档将至少包含那些成员,并且这些成员将被验证。

I assume that all fields are mandatory, so no list can be added neither without a color nor having an item without a title. 我假设所有字段都是必填字段,所以没有颜色的列表和没有标题的项目都不能添加。

I assume that color is an enum also. 我认为颜色也是一个枚举。

{
  validator: {
    name: { $type: 'string', $exists: true },
    color: { $in: ['red', 'green', 'blue'], $exists: true },
    items: { $exists: true },
    $or: [
      { items: { $size: 0 } },
      {
        $and: [
          { 'items.0': { $exists: true } },
          {
            items: {
              $not: {
                $elemMatch: {
                  $not: { $type: 'object' }
                }
              }
            }
          },
          {
            items: {
              $not: {
                $elemMatch: {
                  $or: [
                    { title: { $not: { $type: 'string' } } },
                    { title: { $not: { $exists: true } } },
                    { isDone: { $not: { $type: 'bool' } } },
                    { isDone: { $not: { $exists: true } } },
                    { text: { $not: { $type: 'string' } } },
                    { text: { $not: { $exists: true } } }
                  ]
                }
              }
            }
          }
        ]
      }
    ]
  }
}

Explanation 说明

The solution is based on the second-order logic . 该解决方案基于二阶逻辑 Indeed, the assertion "all elements have to match A" is equal to "no element should match !A" or, if you have many queries, "all element have to match A and B" becomes "no element should match !A or !B", where ! 实际上,断言“所有元素都必须匹配A”等于“没有元素应该匹配!A”,或者,如果您有许多查询,“所有元素必须匹配A和B”变为“没有元素应该匹配!A或B”。 !B”,在哪里! means the negation of the following predicate. 表示以下谓词的否定。

Long explanation 详细说明

The first two query items assert that all documents have name and color , the third one the items property always exists. 前两个查询项目断言所有文档都具有namecolor ,第三个查询items属性始终存在。 NB: in the third query property, there's not the $type check because mongodb treats the array type in a odd way . 注意:在第三个查询属性中,没有$type检查,因为mongodb 以奇怪的方式处理array类型。

The $or operation below is needed because the item property can be empty or filled with some data. 需要下面的$or操作,因为item属性可以为空或可以填充一些数据。

First clause of $or checks if the array is empty. $or第一个子句检查数组是否为空。 If the array is not empty, three checks should be done: 如果数组不为空,则应进行三项检查:

  • the array contains at least one element 数组包含至少一个元素
  • the array has to contain only object 数组必须只包含对象
  • all object has a specified shape. 所有对象都有指定的形状。

So the first $and operator element checks that at least one element is present. 因此,第一个$and运算符元​​素检查是否存在至少一个元素。 The second one checks that all array elements are objects. 第二个检查所有数组元素都是对象。 The third one asserts that all objects have a specified shape. 第三个断言所有对象都具有指定的形状。

In mongodb, there's an operator for checking if all array elements match a query. 在mongodb中,有一个运算符用于检查所有数组元素是否与查询匹配。 So, using the second order logic, the check should be turned over. 因此,应使用二阶逻辑将检查移交。

In fact, the last two clauses of $and check that no elements match none of the described query. 实际上, $and的最后两个子句检查没有元素与所描述的查询匹配。 Each sub query is the negate of a wanted query. 每个子查询都是所需查询的否定项。

Example

fails 失败

{ name: 'foo' }
{ color: 'red' }
{ color: 'unknown color' }
{ name: 'foo', color: 'red' }
{ name: 'foo', color: 'red', item: 3 }
{ name: 'foo', color: 'red', item: [ 3 ] }
{ name: 'foo', color: 'red', item: [ { } ] }
{ name: 'foo', color: 'red', item: [ { title: 'ww' } ] }
{ name: 'foo', color: 'red', item: [ { title: 'ww', isDone: false } ] }
{ name: 'foo', color: 'red', item: [ { title: 44, isDone: false, text: 'the text' } ] }

pass 通过

    { name: 'foo', color: 'red', items: [ ] },
    { name: 'foo', color: 'red', items: [ ] },
    { name: 'foo', color: 'red', items: [ { title: 'the title', isDone: false, text: 'the text' }, { title: 'the title1', isDone: true, text: 'the text' } ] }

This solution is still valid using MongoDB 3.2 该解决方案在MongoDB 3.2上仍然有效

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM