voyageai-cli
Version:
CLI for Voyage AI embeddings, reranking, and MongoDB Atlas Vector Search
277 lines (236 loc) • 7.66 kB
Markdown
# Schema Validation
MongoDB provides flexible schema validation using JSON Schema, allowing you to enforce
document structure at the collection level while preserving the document model's flexibility.
## Creating a Collection with Validation
Use `db.createCollection()` with a `$jsonSchema` validator to enforce structure on insert and update operations.
```javascript
db.createCollection("users", {
validator: {
$jsonSchema: {
bsonType: "object",
title: "User Validation",
required: ["email", "name", "createdAt"],
properties: {
email: {
bsonType: "string",
pattern: "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$",
description: "Must be a valid email address and is required"
},
name: {
bsonType: "string",
minLength: 1,
maxLength: 200,
description: "Full name of the user"
},
age: {
bsonType: "int",
minimum: 0,
maximum: 150,
description: "Age must be an integer between 0 and 150"
},
role: {
enum: ["admin", "editor", "viewer"],
description: "Must be one of the allowed roles"
},
createdAt: {
bsonType: "date",
description: "Timestamp of account creation"
}
}
}
}
})
```
## Required Fields
The `required` array ensures specified fields are present in every document.
```javascript
db.createCollection("products", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["sku", "name", "price", "category"],
properties: {
sku: { bsonType: "string" },
name: { bsonType: "string" },
price: { bsonType: "decimal" },
category: { bsonType: "string" }
}
}
}
})
// This insert will fail — missing required field "category"
db.products.insertOne({ sku: "ABC-123", name: "Widget", price: NumberDecimal("9.99") })
// MongoServerError: Document failed validation
```
## BSON Type Validators
Enforce specific BSON types for fields using `bsonType`.
```javascript
properties: {
count: { bsonType: "int" }, // 32-bit integer
total: { bsonType: "long" }, // 64-bit integer
score: { bsonType: "double" }, // floating point
price: { bsonType: "decimal" }, // Decimal128 (precise)
active: { bsonType: "bool" }, // boolean
tags: { bsonType: "array" }, // array
metadata: { bsonType: "object" }, // embedded document
_id: { bsonType: "objectId" }, // ObjectId
timestamp: { bsonType: "date" } // ISODate
}
```
You can also allow multiple types for a single field:
```javascript
properties: {
value: {
bsonType: ["int", "double", "decimal"],
description: "Accepts any numeric type"
}
}
```
## Enum Validators
Restrict field values to a predefined set.
```javascript
properties: {
status: {
enum: ["pending", "active", "suspended", "deleted"],
description: "Must be a valid account status"
},
priority: {
bsonType: "int",
enum: [1, 2, 3, 4, 5],
description: "Priority level from 1 (highest) to 5 (lowest)"
}
}
```
## Min/Max Validators
Apply numeric range and string length constraints.
```javascript
properties: {
quantity: {
bsonType: "int",
minimum: 0,
maximum: 10000,
description: "Stock quantity must be between 0 and 10,000"
},
discount: {
bsonType: "double",
minimum: 0,
maximum: 1,
description: "Discount as a fraction between 0.0 and 1.0"
},
title: {
bsonType: "string",
minLength: 3,
maxLength: 500
}
}
```
## Nested Document Validation
Validate the structure of embedded documents and arrays of documents.
```javascript
db.createCollection("orders", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["customer", "items", "orderDate"],
properties: {
customer: {
bsonType: "object",
required: ["name", "email"],
properties: {
name: { bsonType: "string" },
email: { bsonType: "string" },
address: {
bsonType: "object",
properties: {
street: { bsonType: "string" },
city: { bsonType: "string" },
state: { bsonType: "string" },
zip: { bsonType: "string" }
}
}
}
},
items: {
bsonType: "array",
minItems: 1,
items: {
bsonType: "object",
required: ["productId", "quantity", "price"],
properties: {
productId: { bsonType: "objectId" },
quantity: { bsonType: "int", minimum: 1 },
price: { bsonType: "decimal" }
}
}
},
orderDate: { bsonType: "date" }
}
}
}
})
```
## Modifying Validation on Existing Collections
Use `collMod` to add or update validation rules on an existing collection.
```javascript
db.runCommand({
collMod: "users",
validator: {
$jsonSchema: {
bsonType: "object",
required: ["email", "name", "role", "createdAt"],
properties: {
email: { bsonType: "string" },
name: { bsonType: "string" },
role: { enum: ["admin", "editor", "viewer", "superadmin"] },
createdAt: { bsonType: "date" }
}
}
},
validationLevel: "moderate",
validationAction: "warn"
})
```
## Validation Level
Controls which documents the validation applies to.
| Level | Behavior |
|--------------|-----------------------------------------------------------------|
| `strict` | Validates all inserts and updates (default) |
| `moderate` | Validates inserts and updates to documents that already match |
| `off` | Disables validation entirely |
```javascript
// Strict: every write must pass validation
db.runCommand({ collMod: "users", validationLevel: "strict" })
// Moderate: existing non-conforming documents can still be updated
db.runCommand({ collMod: "users", validationLevel: "moderate" })
```
## Validation Action
Controls what happens when a document fails validation.
| Action | Behavior |
|----------|----------------------------------------------------|
| `error` | Rejects the write operation (default) |
| `warn` | Allows the write but logs a warning to the server |
```javascript
// Reject invalid documents
db.runCommand({ collMod: "products", validationAction: "error" })
// Allow invalid documents but log warnings
db.runCommand({ collMod: "products", validationAction: "warn" })
```
## Inspecting Existing Validation Rules
```javascript
// View the validation rules for a collection
db.getCollectionInfos({ name: "users" })[0].options.validator
// List all collections with their validation settings
db.getCollectionInfos().forEach(c => {
if (c.options.validator) {
print(`${c.name}: validationLevel=${c.options.validationLevel || "strict"}`)
}
})
```
## Tips
- Start with `validationAction: "warn"` when adding rules to existing collections
to identify non-conforming documents before enforcing strict validation.
- Use `moderate` validation level during migrations so legacy documents are not
blocked from unrelated updates.
- Combine schema validation with unique indexes for complete data integrity.
- In MongoDB Atlas, you can manage validation rules through the Atlas UI under
the collection's Validation tab.