Skip to content

Boolean类型

概述

Boolean(布尔)类型是MongoDB中最简单的数据类型,用于表示逻辑值:真(true)和假(false)。布尔类型在状态标识、条件判断、开关配置等场景中广泛应用,是构建逻辑控制的基础数据类型。

理解布尔类型的特性、存储机制和最佳实践,对于设计清晰的文档结构、优化查询性能和确保数据一致性至关重要。本章节将全面介绍MongoDB中布尔类型的使用方法和注意事项。

基本概念

Boolean类型特性

MongoDB的Boolean类型具有以下核心特性:

1. 二值逻辑

  • 只有两个值:true 和 false
  • 不支持 null 或 undefined 作为布尔值
  • 明确的逻辑状态表示

2. 存储效率

  • 占用1字节存储空间
  • BSON类型标识符:0x08
  • 高效的存储和查询性能

3. 类型转换

  • 支持从其他类型转换为布尔值
  • PHP驱动自动处理类型转换
  • 查询时支持隐式类型转换

4. 查询优化

  • 支持索引创建
  • 高效的等值查询
  • 常用于条件过滤

Boolean类型语法

php
<?php
// 场景说明:演示MongoDB Boolean类型的基本语法和使用方式

// 1. 连接MongoDB数据库
$client = new MongoDB\Client("mongodb://localhost:27017");
$database = $client->selectDatabase("testdb");
$collection = $database->selectCollection("boolean_examples");

// 2. 插入不同类型的布尔数据
$document = [
    'is_active' => true,                    // 用户激活状态
    'is_verified' => false,                 // 验证状态
    'is_admin' => true,                     // 管理员标识
    'has_permission' => false,              // 权限标识
    'is_published' => true,                 // 发布状态
    'is_deleted' => false,                  // 删除标识
    'is_featured' => true,                  // 推荐标识
    'is_premium' => false                   // 高级会员标识
];

// 关键行注释:插入包含各种布尔值的文档
$result = $collection->insertOne($document);
echo "插入成功,文档ID: " . $result->getInsertedId() . "\n";

// 3. 布尔值查询操作
// 查询激活用户
$activeUsers = $collection->find(['is_active' => true])->toArray();
echo "激活用户数量: " . count($activeUsers) . "\n";

// 查询未验证用户
$unverifiedUsers = $collection->find(['is_verified' => false])->toArray();
echo "未验证用户数量: " . count($unverifiedUsers) . "\n";

// 查询管理员且已发布
$adminPublished = $collection->find([
    'is_admin' => true,
    'is_published' => true
])->toArray();
echo "管理员且已发布数量: " . count($adminPublished) . "\n";

// 4. 布尔值更新操作
// 激活用户
$collection->updateOne(
    ['is_active' => false],
    ['$set' => ['is_active' => true]]
);
echo "用户已激活\n";

// 运行结果展示:
// 插入成功,文档ID: 507f1f77bcf86cd799439011
// 激活用户数量: 1
// 未验证用户数量: 1
// 管理员且已发布数量: 1
// 用户已激活
?>

常见改法对比

php
<?php
// 错误示例:使用字符串表示布尔值
$collection->insertOne([
    'is_active' => 'true',      // 错误:字符串而非布尔值
    'is_verified' => 'false'    // 错误:字符串而非布尔值
]);

// 查询时会失败
$result = $collection->findOne(['is_active' => true]);  // 查询不到

// 正确示例:使用真正的布尔值
$collection->insertOne([
    'is_active' => true,        // 正确:布尔值
    'is_verified' => false      // 正确:布尔值
]);

// 查询成功
$result = $collection->findOne(['is_active' => true]);  // 查询成功

// 错误示例:使用整数表示布尔值
$collection->insertOne([
    'is_active' => 1,           // 错误:整数而非布尔值
    'is_verified' => 0          // 错误:整数而非布尔值
]);

// 正确示例:类型转换后存储
$collection->insertOne([
    'is_active' => (bool)1,     // 正确:转换为布尔值
    'is_verified' => (bool)0    // 正确:转换为布尔值
]);
?>

Boolean类型规范

1. 命名规范

  • 使用is_、has_、can_等前缀
  • 名称应清晰表达布尔含义
  • 避免使用否定词(如is_not_active)

2. 存储规范

  • 统一使用true/false,不使用1/0
  • 避免使用字符串"true"/"false"
  • 保持字段类型一致性

3. 查询规范

  • 直接使用布尔值查询
  • 避免类型转换
  • 为常用布尔字段创建索引

原理深度解析

Boolean存储机制

MongoDB使用BSON格式存储Boolean,存储结构简单高效:

存储结构

[类型标识(1字节)] + [布尔值(1字节)]

存储细节

  • 类型标识:0x08
  • true值:0x01
  • false值:0x00
  • 总占用:2字节
php
<?php
// 场景说明:深入分析Boolean的存储机制和性能特性

class BooleanStorageAnalyzer {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    // 分析布尔值存储
    public function analyzeBooleanStorage() {
        $collection = $this->database->selectCollection('boolean_storage');
        
        // 插入测试数据
        $testCases = [
            'true_value' => true,
            'false_value' => false,
            'multiple_true' => ['a' => true, 'b' => true, 'c' => true],
            'multiple_false' => ['a' => false, 'b' => false, 'c' => false],
            'mixed' => ['a' => true, 'b' => false, 'c' => true]
        ];
        
        foreach ($testCases as $name => $value) {
            $collection->insertOne([
                'name' => $name,
                'value' => $value,
                'created_at' => new MongoDB\BSON\UTCDateTime()
            ]);
        }
        
        // 关键行注释:分析存储大小
        $stats = $collection->stats();
        
        return [
            'document_count' => $collection->countDocuments(),
            'storage_size' => $stats['size'],
            'average_size' => $stats['size'] / $collection->countDocuments()
        ];
    }
    
    // 比较不同表示方式的存储效率
    public function compareStorageEfficiency() {
        $collection = $this->database->selectCollection('storage_comparison');
        
        // 方法1:使用布尔值
        $collection->insertOne([
            'method' => 'boolean',
            'value' => true,
            'storage_bytes' => 2
        ]);
        
        // 方法2:使用整数
        $collection->insertOne([
            'method' => 'integer',
            'value' => 1,
            'storage_bytes' => 4
        ]);
        
        // 方法3:使用字符串
        $collection->insertOne([
            'method' => 'string',
            'value' => 'true',
            'storage_bytes' => 6
        ]);
        
        return [
            'boolean' => '2 bytes (最优)',
            'integer' => '4 bytes',
            'string' => '6+ bytes (最差)'
        ];
    }
    
    // 性能测试
    public function performanceTest() {
        $collection = $this->database->selectCollection('performance_test');
        
        // 插入大量布尔数据
        for ($i = 0; $i < 10000; $i++) {
            $collection->insertOne([
                'is_active' => (bool)($i % 2),
                'is_verified' => (bool)($i % 3),
                'index' => $i
            ]);
        }
        
        // 创建索引
        $collection->createIndex(['is_active' => 1]);
        
        // 测试查询性能
        $startTime = microtime(true);
        $results = $collection->find(['is_active' => true])->toArray();
        $queryTime = microtime(true) - $startTime;
        
        return [
            'total_documents' => 10000,
            'matching_documents' => count($results),
            'query_time' => $queryTime,
            'index_used' => true
        ];
    }
}

// 使用示例
$analyzer = new BooleanStorageAnalyzer('testdb');

$storage = $analyzer->analyzeBooleanStorage();
print_r($storage);

$efficiency = $analyzer->compareStorageEfficiency();
print_r($efficiency);

$performance = $analyzer->performanceTest();
print_r($performance);
?>

Boolean查询优化

php
<?php
// 场景说明:演示布尔值的查询优化技术

class BooleanQueryOptimizer {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    // 创建优化的索引
    public function createOptimizedIndexes() {
        $collection = $this->database->selectCollection('optimized_queries');
        
        // 关键行注释:为布尔字段创建索引
        $collection->createIndex(['is_active' => 1]);
        $collection->createIndex(['is_verified' => 1, 'is_active' => 1]);
        
        return ['indexes_created' => 2];
    }
    
    // 优化查询示例
    public function optimizedQueries() {
        $collection = $this->database->selectCollection('optimized_queries');
        
        // 插入测试数据
        for ($i = 0; $i < 1000; $i++) {
            $collection->insertOne([
                'user_id' => $i,
                'is_active' => (bool)($i % 2),
                'is_verified' => (bool)($i % 3),
                'is_premium' => (bool)($i % 5)
            ]);
        }
        
        // 查询1:简单布尔查询
        $query1Start = microtime(true);
        $results1 = $collection->find(['is_active' => true])->toArray();
        $query1Time = microtime(true) - $query1Start;
        
        // 查询2:复合布尔查询
        $query2Start = microtime(true);
        $results2 = $collection->find([
            'is_active' => true,
            'is_verified' => true
        ])->toArray();
        $query2Time = microtime(true) - $query2Start;
        
        // 查询3:使用$or操作符
        $query3Start = microtime(true);
        $results3 = $collection->find([
            '$or' => [
                ['is_active' => true],
                ['is_verified' => true]
            ]
        ])->toArray();
        $query3Time = microtime(true) - $query3Start;
        
        return [
            'simple_query' => [
                'count' => count($results1),
                'time' => $query1Time
            ],
            'compound_query' => [
                'count' => count($results2),
                'time' => $query2Time
            ],
            'or_query' => [
                'count' => count($results3),
                'time' => $query3Time
            ]
        ];
    }
    
    // 聚合统计
    public function booleanAggregation() {
        $collection = $this->database->selectCollection('optimized_queries');
        
        $pipeline = [
            [
                '$group' => [
                    '_id' => null,
                    'total_active' => [
                        '$sum' => ['$cond' => ['$is_active', 1, 0]]
                    ],
                    'total_verified' => [
                        '$sum' => ['$cond' => ['$is_verified', 1, 0]]
                    ],
                    'total_premium' => [
                        '$sum' => ['$cond' => ['$is_premium', 1, 0]]
                    ]
                ]
            ]
        ];
        
        return $collection->aggregate($pipeline)->toArray();
    }
}

// 使用示例
$optimizer = new BooleanQueryOptimizer('testdb');
$optimizer->createOptimizedIndexes();
$results = $optimizer->optimizedQueries();
print_r($results);

$aggregation = $optimizer->booleanAggregation();
print_r($aggregation);
?>

常见错误与踩坑点

错误1:类型混淆

错误表现

  • 使用字符串"true"/"false"代替布尔值
  • 使用整数1/0代替布尔值
  • 查询不到预期结果

产生原因

  • 未正确理解布尔类型
  • 数据来源不一致
  • 缺少类型验证

解决方案

php
<?php
// 场景说明:演示布尔值类型混淆的正确处理

class BooleanTypeHandler {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    // 错误示例:类型混淆
    public function wrongTypeExample() {
        $collection = $this->database->selectCollection('wrong_type');
        
        // 错误:使用字符串
        $collection->insertOne([
            'is_active' => 'true',      // 字符串,不是布尔值
            'is_verified' => 'false'
        ]);
        
        // 查询失败
        $result = $collection->findOne(['is_active' => true]);
        
        if (!$result) {
            echo "错误:类型不匹配导致查询失败\n";
        }
        
        // 错误:使用整数
        $collection->insertOne([
            'is_active' => 1,           // 整数,不是布尔值
            'is_verified' => 0
        ]);
        
        // 查询失败
        $result = $collection->findOne(['is_active' => true]);
        
        if (!$result) {
            echo "错误:整数与布尔值类型不匹配\n";
        }
    }
    
    // 正确示例:统一使用布尔值
    public function correctTypeExample() {
        $collection = $this->database->selectCollection('correct_type');
        
        // 正确:使用布尔值
        $collection->insertOne([
            'is_active' => true,        // 布尔值
            'is_verified' => false
        ]);
        
        // 查询成功
        $result = $collection->findOne(['is_active' => true]);
        
        if ($result) {
            echo "正确:类型匹配查询成功\n";
        }
    }
    
    // 类型转换工具
    public function ensureBoolean($value) {
        if (is_bool($value)) {
            return $value;
        } elseif (is_string($value)) {
            return filter_var($value, FILTER_VALIDATE_BOOLEAN);
        } elseif (is_int($value)) {
            return (bool)$value;
        } elseif (is_null($value)) {
            return false;
        }
        
        return (bool)$value;
    }
    
    // 批量转换
    public function convertToBoolean($data, $fields) {
        foreach ($fields as $field) {
            if (isset($data[$field])) {
                $data[$field] = $this->ensureBoolean($data[$field]);
            }
        }
        
        return $data;
    }
}

// 使用示例
$handler = new BooleanTypeHandler('testdb');
$handler->wrongTypeExample();
$handler->correctTypeExample();

// 类型转换
$boolValue = $handler->ensureBoolean('true');
echo "转换结果: " . ($boolValue ? 'true' : 'false') . "\n";

$data = [
    'is_active' => 'yes',
    'is_verified' => 1,
    'is_premium' => 'false'
];

$converted = $handler->convertToBoolean($data, ['is_active', 'is_verified', 'is_premium']);
print_r($converted);
?>

错误2:布尔字段命名不当

错误表现

  • 使用否定词命名(如is_not_active)
  • 命名不清晰(如flag、status)
  • 双重否定导致逻辑混乱

产生原因

  • 缺少命名规范
  • 未考虑逻辑清晰性
  • 历史遗留问题

解决方案

php
<?php
// 场景说明:演示布尔字段命名的最佳实践

class BooleanNamingHandler {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    // 错误示例:命名不当
    public function wrongNamingExample() {
        $collection = $this->database->selectCollection('wrong_naming');
        
        // 错误:使用否定词
        $collection->insertOne([
            'is_not_active' => false,       // 双重否定,逻辑混乱
            'is_not_deleted' => true,       // 难以理解
            'flag' => true,                 // 不清晰
            'status' => false               // 含义不明
        ]);
        
        echo "错误:命名不当导致逻辑混乱\n";
    }
    
    // 正确示例:清晰的命名
    public function correctNamingExample() {
        $collection = $this->database->selectCollection('correct_naming');
        
        // 正确:使用肯定词和清晰的前缀
        $collection->insertOne([
            'is_active' => true,            // 清晰:是否激活
            'is_deleted' => false,          // 清晰:是否删除
            'has_permission' => true,       // 清晰:是否有权限
            'can_edit' => true,             // 清晰:是否能编辑
            'should_notify' => false        // 清晰:是否应通知
        ]);
        
        echo "正确:命名清晰,逻辑明确\n";
    }
    
    // 命名建议
    public function namingGuidelines() {
        return [
            'prefixes' => [
                'is_' => '表示状态(如:is_active, is_published)',
                'has_' => '表示拥有(如:has_permission, has_avatar)',
                'can_' => '表示能力(如:can_edit, can_delete)',
                'should_' => '表示建议(如:should_notify, should_archive)',
                'was_' => '表示历史状态(如:was_processed, was_sent)'
            ],
            'avoid' => [
                'is_not_' => '避免否定词',
                'flag' => '避免通用词',
                'status' => '避免模糊词'
            ],
            'examples' => [
                'good' => ['is_active', 'has_permission', 'can_edit'],
                'bad' => ['is_not_inactive', 'flag1', 'status_bool']
            ]
        ];
    }
}

// 使用示例
$handler = new BooleanNamingHandler('testdb');
$handler->wrongNamingExample();
$handler->correctNamingExample();

$guidelines = $handler->namingGuidelines();
print_r($guidelines);
?>

错误3:过度使用布尔字段

错误表现

  • 用多个布尔字段表示状态
  • 布尔字段过多导致维护困难
  • 状态逻辑复杂

产生原因

  • 设计不当
  • 未考虑状态机
  • 缺少重构

解决方案

php
<?php
// 场景说明:演示布尔字段的合理使用

class BooleanDesignHandler {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    // 错误示例:过度使用布尔字段
    public function wrongDesignExample() {
        $collection = $this->database->selectCollection('wrong_design');
        
        // 错误:用多个布尔字段表示状态
        $collection->insertOne([
            'is_draft' => false,
            'is_published' => true,
            'is_archived' => false,
            'is_deleted' => false,
            'is_pending' => false
        ]);
        
        echo "错误:多个布尔字段表示状态,容易冲突\n";
    }
    
    // 正确示例:使用状态字段
    public function correctDesignExample() {
        $collection = $this->database->selectCollection('correct_design');
        
        // 正确:使用单一状态字段
        $collection->insertOne([
            'status' => 'published',  // draft, published, archived, deleted
            'published_at' => new MongoDB\BSON\UTCDateTime()
        ]);
        
        echo "正确:使用状态字段,逻辑清晰\n";
    }
    
    // 状态机设计
    public function stateMachineDesign() {
        $collection = $this->database->selectCollection('state_machine');
        
        $states = [
            'draft' => [
                'can_transition_to' => ['published', 'deleted']
            ],
            'published' => [
                'can_transition_to' => ['archived', 'deleted']
            ],
            'archived' => [
                'can_transition_to' => ['published', 'deleted']
            ],
            'deleted' => [
                'can_transition_to' => []
            ]
        ];
        
        return $states;
    }
    
    // 合理使用布尔字段的场景
    public function appropriateUseCases() {
        return [
            'good_cases' => [
                'is_active' => '用户激活状态',
                'is_verified' => '邮箱验证状态',
                'has_permission' => '权限标识',
                'can_edit' => '编辑权限',
                'is_featured' => '推荐标识'
            ],
            'bad_cases' => [
                'is_draft + is_published' => '应使用status字段',
                'is_pending + is_approved' => '应使用workflow字段',
                'is_active + is_inactive' => '冗余设计'
            ]
        ];
    }
}

// 使用示例
$handler = new BooleanDesignHandler('testdb');
$handler->wrongDesignExample();
$handler->correctDesignExample();

$states = $handler->stateMachineDesign();
print_r($states);

$useCases = $handler->appropriateUseCases();
print_r($useCases);
?>

常见应用场景

场景1:用户状态管理

场景描述:管理用户的激活、验证等状态。

使用方法

  • 使用布尔字段标识用户状态
  • 创建索引提高查询性能
  • 使用复合查询过滤用户

示例代码

php
<?php
// 场景说明:用户状态管理系统

class UserStatusManager {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    // 初始化索引
    public function initializeIndexes() {
        $collection = $this->database->selectCollection('users');
        
        // 关键行注释:为布尔字段创建索引
        $collection->createIndex(['is_active' => 1]);
        $collection->createIndex(['is_verified' => 1]);
        $collection->createIndex(['is_active' => 1, 'is_verified' => 1]);
    }
    
    // 创建用户
    public function createUser($userData) {
        $collection = $this->database->selectCollection('users');
        
        $user = [
            'username' => $userData['username'],
            'email' => $userData['email'],
            'is_active' => false,           // 默认未激活
            'is_verified' => false,         // 默认未验证
            'is_admin' => false,            // 默认非管理员
            'is_premium' => false,          // 默认非高级会员
            'created_at' => new MongoDB\BSON\UTCDateTime()
        ];
        
        $result = $collection->insertOne($user);
        
        return (string)$result->getInsertedId();
    }
    
    // 激活用户
    public function activateUser($userId) {
        $collection = $this->database->selectCollection('users');
        
        $result = $collection->updateOne(
            ['_id' => new MongoDB\BSON\ObjectId($userId)],
            [
                '$set' => [
                    'is_active' => true,
                    'activated_at' => new MongoDB\BSON\UTCDateTime()
                ]
            ]
        );
        
        return $result->getModifiedCount() > 0;
    }
    
    // 验证邮箱
    public function verifyEmail($userId) {
        $collection = $this->database->selectCollection('users');
        
        $result = $collection->updateOne(
            ['_id' => new MongoDB\BSON\ObjectId($userId)],
            [
                '$set' => [
                    'is_verified' => true,
                    'verified_at' => new MongoDB\BSON\UTCDateTime()
                ]
            ]
        );
        
        return $result->getModifiedCount() > 0;
    }
    
    // 查询激活用户
    public function getActiveUsers($limit = 10) {
        $collection = $this->database->selectCollection('users');
        
        return $collection->find(
            ['is_active' => true],
            ['limit' => $limit]
        )->toArray();
    }
    
    // 查询激活且验证的用户
    public function getActiveVerifiedUsers($limit = 10) {
        $collection = $this->database->selectCollection('users');
        
        return $collection->find(
            [
                'is_active' => true,
                'is_verified' => true
            ],
            ['limit' => $limit]
        )->toArray();
    }
    
    // 统计用户状态
    public function getUserStats() {
        $collection = $this->database->selectCollection('users');
        
        $pipeline = [
            [
                '$group' => [
                    '_id' => null,
                    'total' => ['$sum' => 1],
                    'active' => ['$sum' => ['$cond' => ['$is_active', 1, 0]]],
                    'verified' => ['$sum' => ['$cond' => ['$is_verified', 1, 0]]],
                    'admin' => ['$sum' => ['$cond' => ['$is_admin', 1, 0]]]
                ]
            ]
        ];
        
        return $collection->aggregate($pipeline)->toArray();
    }
}

// 使用示例
$manager = new UserStatusManager('user_db');
$manager->initializeIndexes();

// 创建用户
$userId = $manager->createUser([
    'username' => 'john_doe',
    'email' => 'john@example.com'
]);
echo "用户ID: $userId\n";

// 激活用户
$manager->activateUser($userId);
echo "用户已激活\n";

// 验证邮箱
$manager->verifyEmail($userId);
echo "邮箱已验证\n";

// 查询用户
$activeUsers = $manager->getActiveUsers();
echo "激活用户数量: " . count($activeUsers) . "\n";

// 统计
$stats = $manager->getUserStats();
print_r($stats);
?>

场景2:内容发布系统

场景描述:管理文章的发布、推荐等状态。

示例代码

php
<?php
// 场景说明:内容发布系统

class ContentPublishingSystem {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    // 创建文章
    public function createArticle($articleData) {
        $collection = $this->database->selectCollection('articles');
        
        $article = [
            'title' => $articleData['title'],
            'content' => $articleData['content'],
            'author_id' => $articleData['author_id'],
            'is_published' => false,        // 默认未发布
            'is_featured' => false,         // 默认不推荐
            'is_pinned' => false,           // 默认不置顶
            'is_commentable' => true,       // 默认可评论
            'created_at' => new MongoDB\BSON\UTCDateTime()
        ];
        
        $result = $collection->insertOne($article);
        
        return (string)$result->getInsertedId();
    }
    
    // 发布文章
    public function publishArticle($articleId) {
        $collection = $this->database->selectCollection('articles');
        
        $result = $collection->updateOne(
            ['_id' => new MongoDB\BSON\ObjectId($articleId)],
            [
                '$set' => [
                    'is_published' => true,
                    'published_at' => new MongoDB\BSON\UTCDateTime()
                ]
            ]
        );
        
        return $result->getModifiedCount() > 0;
    }
    
    // 设置推荐
    public function setFeatured($articleId, $featured = true) {
        $collection = $this->database->selectCollection('articles');
        
        $result = $collection->updateOne(
            ['_id' => new MongoDB\BSON\ObjectId($articleId)],
            ['$set' => ['is_featured' => $featured]]
        );
        
        return $result->getModifiedCount() > 0;
    }
    
    // 查询已发布文章
    public function getPublishedArticles($limit = 10) {
        $collection = $this->database->selectCollection('articles');
        
        return $collection->find(
            ['is_published' => true],
            [
                'sort' => ['published_at' => -1],
                'limit' => $limit
            ]
        )->toArray();
    }
    
    // 查询推荐文章
    public function getFeaturedArticles($limit = 5) {
        $collection = $this->database->selectCollection('articles');
        
        return $collection->find(
            [
                'is_published' => true,
                'is_featured' => true
            ],
            [
                'sort' => ['published_at' => -1],
                'limit' => $limit
            ]
        )->toArray();
    }
}

// 使用示例
$system = new ContentPublishingSystem('content_db');

// 创建文章
$articleId = $system->createArticle([
    'title' => 'MongoDB Boolean Type Tutorial',
    'content' => 'This is a tutorial about MongoDB boolean type...',
    'author_id' => 'author_001'
]);
echo "文章ID: $articleId\n";

// 发布文章
$system->publishArticle($articleId);
echo "文章已发布\n";

// 设置推荐
$system->setFeatured($articleId, true);
echo "文章已推荐\n";

// 查询文章
$published = $system->getPublishedArticles();
echo "已发布文章数量: " . count($published) . "\n";

$featured = $system->getFeaturedArticles();
echo "推荐文章数量: " . count($featured) . "\n";
?>

场景3:权限控制系统

场景描述:管理用户的权限和访问控制。

示例代码

php
<?php
// 场景说明:权限控制系统

class PermissionControlSystem {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    // 创建用户权限
    public function createUserPermissions($userId, $permissions) {
        $collection = $this->database->selectCollection('user_permissions');
        
        $doc = [
            'user_id' => $userId,
            'can_read' => $permissions['can_read'] ?? false,
            'can_write' => $permissions['can_write'] ?? false,
            'can_delete' => $permissions['can_delete'] ?? false,
            'can_admin' => $permissions['can_admin'] ?? false,
            'can_share' => $permissions['can_share'] ?? false,
            'created_at' => new MongoDB\BSON\UTCDateTime()
        ];
        
        $result = $collection->insertOne($doc);
        
        return (string)$result->getInsertedId();
    }
    
    // 检查权限
    public function hasPermission($userId, $permission) {
        $collection = $this->database->selectCollection('user_permissions');
        
        $result = $collection->findOne(['user_id' => $userId]);
        
        if (!$result) {
            return false;
        }
        
        return isset($result[$permission]) ? $result[$permission] : false;
    }
    
    // 授予权限
    public function grantPermission($userId, $permission) {
        $collection = $this->database->selectCollection('user_permissions');
        
        $result = $collection->updateOne(
            ['user_id' => $userId],
            ['$set' => [$permission => true]]
        );
        
        return $result->getModifiedCount() > 0;
    }
    
    // 撤销权限
    public function revokePermission($userId, $permission) {
        $collection = $this->database->selectCollection('user_permissions');
        
        $result = $collection->updateOne(
            ['user_id' => $userId],
            ['$set' => [$permission => false]]
        );
        
        return $result->getModifiedCount() > 0;
    }
    
    // 查询有特定权限的用户
    public function getUsersWithPermission($permission) {
        $collection = $this->database->selectCollection('user_permissions');
        
        return $collection->find(
            [$permission => true]
        )->toArray();
    }
}

// 使用示例
$system = new PermissionControlSystem('permission_db');

// 创建权限
$system->createUserPermissions('user_001', [
    'can_read' => true,
    'can_write' => true,
    'can_delete' => false,
    'can_admin' => false
]);

// 检查权限
$canWrite = $system->hasPermission('user_001', 'can_write');
echo "用户是否有写权限: " . ($canWrite ? '是' : '否') . "\n";

// 授予权限
$system->grantPermission('user_001', 'can_delete');
echo "已授予删除权限\n";

// 撤销权限
$system->revokePermission('user_001', 'can_write');
echo "已撤销写权限\n";
?>

场景4:功能开关系统

场景描述:管理应用功能的开关状态。

示例代码

php
<?php
// 场景说明:功能开关系统

class FeatureFlagSystem {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    // 创建功能开关
    public function createFeatureFlag($name, $enabled = false) {
        $collection = $this->database->selectCollection('feature_flags');
        
        $flag = [
            'name' => $name,
            'is_enabled' => $enabled,
            'created_at' => new MongoDB\BSON\UTCDateTime(),
            'updated_at' => new MongoDB\BSON\UTCDateTime()
        ];
        
        $result = $collection->insertOne($flag);
        
        return (string)$result->getInsertedId();
    }
    
    // 检查功能是否启用
    public function isFeatureEnabled($name) {
        $collection = $this->database->selectCollection('feature_flags');
        
        $result = $collection->findOne(['name' => $name]);
        
        return $result ? $result['is_enabled'] : false;
    }
    
    // 启用功能
    public function enableFeature($name) {
        $collection = $this->database->selectCollection('feature_flags');
        
        $result = $collection->updateOne(
            ['name' => $name],
            [
                '$set' => [
                    'is_enabled' => true,
                    'updated_at' => new MongoDB\BSON\UTCDateTime()
                ]
            ]
        );
        
        return $result->getModifiedCount() > 0;
    }
    
    // 禁用功能
    public function disableFeature($name) {
        $collection = $this->database->selectCollection('feature_flags');
        
        $result = $collection->updateOne(
            ['name' => $name],
            [
                '$set' => [
                    'is_enabled' => false,
                    'updated_at' => new MongoDB\BSON\UTCDateTime()
                ]
            ]
        );
        
        return $result->getModifiedCount() > 0;
    }
    
    // 获取所有启用的功能
    public function getEnabledFeatures() {
        $collection = $this->database->selectCollection('feature_flags');
        
        return $collection->find(
            ['is_enabled' => true]
        )->toArray();
    }
}

// 使用示例
$system = new FeatureFlagSystem('feature_db');

// 创建功能开关
$system->createFeatureFlag('new_dashboard', false);
$system->createFeatureFlag('dark_mode', true);
$system->createFeatureFlag('beta_features', false);

// 检查功能状态
$isEnabled = $system->isFeatureEnabled('dark_mode');
echo "暗黑模式是否启用: " . ($isEnabled ? '是' : '否') . "\n";

// 启用功能
$system->enableFeature('new_dashboard');
echo "新仪表板已启用\n";

// 禁用功能
$system->disableFeature('beta_features');
echo "测试功能已禁用\n";

// 获取所有启用的功能
$enabled = $system->getEnabledFeatures();
echo "启用的功能数量: " . count($enabled) . "\n";
?>

场景5:通知设置系统

场景描述:管理用户的通知偏好设置。

示例代码

php
<?php
// 场景说明:通知设置系统

class NotificationSettingsSystem {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    // 创建通知设置
    public function createNotificationSettings($userId) {
        $collection = $this->database->selectCollection('notification_settings');
        
        $settings = [
            'user_id' => $userId,
            'email_enabled' => true,
            'push_enabled' => true,
            'sms_enabled' => false,
            'marketing_enabled' => false,
            'mentions_enabled' => true,
            'comments_enabled' => true,
            'created_at' => new MongoDB\BSON\UTCDateTime()
        ];
        
        $result = $collection->insertOne($settings);
        
        return (string)$result->getInsertedId();
    }
    
    // 更新通知设置
    public function updateSettings($userId, $settings) {
        $collection = $this->database->selectCollection('notification_settings');
        
        $updateData = [];
        foreach ($settings as $key => $value) {
            if (in_array($key, ['email_enabled', 'push_enabled', 'sms_enabled', 
                               'marketing_enabled', 'mentions_enabled', 'comments_enabled'])) {
                $updateData[$key] = (bool)$value;
            }
        }
        
        $result = $collection->updateOne(
            ['user_id' => $userId],
            ['$set' => $updateData]
        );
        
        return $result->getModifiedCount() > 0;
    }
    
    // 获取用户设置
    public function getUserSettings($userId) {
        $collection = $this->database->selectCollection('notification_settings');
        
        return $collection->findOne(['user_id' => $userId]);
    }
    
    // 查询启用了特定通知的用户
    public function getUsersWithNotificationEnabled($type) {
        $collection = $this->database->selectCollection('notification_settings');
        
        return $collection->find(
            [$type . '_enabled' => true]
        )->toArray();
    }
}

// 使用示例
$system = new NotificationSettingsSystem('notification_db');

// 创建通知设置
$system->createNotificationSettings('user_001');

// 更新设置
$system->updateSettings('user_001', [
    'email_enabled' => true,
    'push_enabled' => false,
    'marketing_enabled' => false
]);

// 获取设置
$settings = $system->getUserSettings('user_001');
print_r($settings);

// 查询启用了邮件通知的用户
$emailUsers = $system->getUsersWithNotificationEnabled('email');
echo "启用邮件通知的用户数量: " . count($emailUsers) . "\n";
?>

企业级进阶应用场景

场景1:多维度权限系统

场景描述:实现复杂的多维度权限控制。

示例代码

php
<?php
// 场景说明:多维度权限系统

class MultiDimensionalPermissionSystem {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    // 创建角色权限
    public function createRolePermissions($roleName, $permissions) {
        $collection = $this->database->selectCollection('role_permissions');
        
        $doc = [
            'role_name' => $roleName,
            'permissions' => $permissions,
            'created_at' => new MongoDB\BSON\UTCDateTime()
        ];
        
        $result = $collection->insertOne($doc);
        
        return (string)$result->getInsertedId();
    }
    
    // 检查权限
    public function checkPermission($roleName, $resource, $action) {
        $collection = $this->database->selectCollection('role_permissions');
        
        $result = $collection->findOne(['role_name' => $roleName]);
        
        if (!$result) {
            return false;
        }
        
        $permissionKey = "can_{$action}_{$resource}";
        
        return isset($result['permissions'][$permissionKey]) ? 
            $result['permissions'][$permissionKey] : false;
    }
    
    // 批量检查权限
    public function checkMultiplePermissions($roleName, $permissionChecks) {
        $results = [];
        
        foreach ($permissionChecks as $check) {
            $results[$check['resource'] . '_' . $check['action']] = 
                $this->checkPermission($roleName, $check['resource'], $check['action']);
        }
        
        return $results;
    }
    
    // 获取用户的所有权限
    public function getUserPermissions($userId) {
        $userCollection = $this->database->selectCollection('users');
        $roleCollection = $this->database->selectCollection('role_permissions');
        
        $user = $userCollection->findOne(['_id' => new MongoDB\BSON\ObjectId($userId)]);
        
        if (!$user || !isset($user['roles'])) {
            return [];
        }
        
        $allPermissions = [];
        
        foreach ($user['roles'] as $roleName) {
            $role = $roleCollection->findOne(['role_name' => $roleName]);
            
            if ($role && isset($role['permissions'])) {
                foreach ($role['permissions'] as $key => $value) {
                    if ($value) {
                        $allPermissions[$key] = true;
                    }
                }
            }
        }
        
        return $allPermissions;
    }
}

// 使用示例
$system = new MultiDimensionalPermissionSystem('enterprise_db');

// 创建角色权限
$system->createRolePermissions('admin', [
    'can_read_users' => true,
    'can_write_users' => true,
    'can_delete_users' => true,
    'can_read_articles' => true,
    'can_write_articles' => true,
    'can_delete_articles' => true
]);

$system->createRolePermissions('editor', [
    'can_read_users' => true,
    'can_write_users' => false,
    'can_delete_users' => false,
    'can_read_articles' => true,
    'can_write_articles' => true,
    'can_delete_articles' => false
]);

// 检查权限
$canDelete = $system->checkPermission('admin', 'users', 'delete');
echo "管理员是否可以删除用户: " . ($canDelete ? '是' : '否') . "\n";

// 批量检查
$checks = $system->checkMultiplePermissions('editor', [
    ['resource' => 'users', 'action' => 'read'],
    ['resource' => 'users', 'action' => 'delete'],
    ['resource' => 'articles', 'action' => 'write']
]);
print_r($checks);
?>

场景2:A/B测试系统

场景描述:实现功能开关和A/B测试。

示例代码

php
<?php
// 场景说明:A/B测试系统

class ABTestingSystem {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    // 创建实验
    public function createExperiment($name, $variants) {
        $collection = $this->database->selectCollection('experiments');
        
        $experiment = [
            'name' => $name,
            'is_active' => true,
            'variants' => $variants,
            'created_at' => new MongoDB\BSON\UTCDateTime()
        ];
        
        $result = $collection->insertOne($experiment);
        
        return (string)$result->getInsertedId();
    }
    
    // 分配用户到实验组
    public function assignUserToVariant($experimentName, $userId) {
        $collection = $this->database->selectCollection('experiments');
        $assignmentCollection = $this->database->selectCollection('experiment_assignments');
        
        $experiment = $collection->findOne([
            'name' => $experimentName,
            'is_active' => true
        ]);
        
        if (!$experiment) {
            return null;
        }
        
        // 检查是否已分配
        $existing = $assignmentCollection->findOne([
            'experiment_name' => $experimentName,
            'user_id' => $userId
        ]);
        
        if ($existing) {
            return $existing['variant'];
        }
        
        // 随机分配
        $variants = $experiment['variants'];
        $variant = $variants[array_rand($variants)];
        
        $assignmentCollection->insertOne([
            'experiment_name' => $experimentName,
            'user_id' => $userId,
            'variant' => $variant,
            'assigned_at' => new MongoDB\BSON\UTCDateTime()
        ]);
        
        return $variant;
    }
    
    // 检查用户是否在实验组
    public function isInExperiment($experimentName, $userId, $variant = null) {
        $collection = $this->database->selectCollection('experiment_assignments');
        
        $query = [
            'experiment_name' => $experimentName,
            'user_id' => $userId
        ];
        
        if ($variant) {
            $query['variant'] = $variant;
        }
        
        $result = $collection->findOne($query);
        
        return $result !== null;
    }
    
    // 获取实验统计
    public function getExperimentStats($experimentName) {
        $collection = $this->database->selectCollection('experiment_assignments');
        
        $pipeline = [
            [
                '$match' => ['experiment_name' => $experimentName]
            ],
            [
                '$group' => [
                    '_id' => '$variant',
                    'count' => ['$sum' => 1]
                ]
            ]
        ];
        
        return $collection->aggregate($pipeline)->toArray();
    }
    
    // 启用/禁用实验
    public function toggleExperiment($experimentName, $active) {
        $collection = $this->database->selectCollection('experiments');
        
        $result = $collection->updateOne(
            ['name' => $experimentName],
            ['$set' => ['is_active' => $active]]
        );
        
        return $result->getModifiedCount() > 0;
    }
}

// 使用示例
$system = new ABTestingSystem('abtest_db');

// 创建实验
$system->createExperiment('new_ui_design', ['control', 'variant_a', 'variant_b']);

// 分配用户
$variant = $system->assignUserToVariant('new_ui_design', 'user_001');
echo "用户分配到: $variant\n";

// 检查用户是否在实验组
$inExperiment = $system->isInExperiment('new_ui_design', 'user_001');
echo "用户是否在实验中: " . ($inExperiment ? '是' : '否') . "\n";

// 获取统计
$stats = $system->getExperimentStats('new_ui_design');
print_r($stats);
?>

行业最佳实践

实践1:使用清晰的命名

实践内容

  • 使用is_、has_、can_等前缀
  • 避免否定词
  • 名称应清晰表达含义

推荐理由

  • 提高代码可读性
  • 避免逻辑混乱
  • 便于维护
php
<?php
// 好的实践:清晰的命名
$goodExamples = [
    'is_active' => '用户是否激活',
    'has_permission' => '是否有权限',
    'can_edit' => '是否能编辑',
    'should_notify' => '是否应通知'
];

// 不好的实践:不清晰的命名
$badExamples = [
    'is_not_inactive' => '双重否定,难以理解',
    'flag' => '含义不明',
    'status_bool' => '冗余命名'
];
?>

实践2:创建合适的索引

实践内容

  • 为常用布尔字段创建索引
  • 使用复合索引优化查询
  • 定期监控索引使用情况

推荐理由

  • 提高查询性能
  • 减少资源消耗
  • 优化用户体验
php
<?php
// 好的实践:创建索引
$collection->createIndex(['is_active' => 1]);
$collection->createIndex(['is_active' => 1, 'is_verified' => 1]);
?>

实践3:避免过度使用布尔字段

实践内容

  • 用状态字段代替多个布尔字段
  • 设计合理的状态机
  • 保持逻辑清晰

推荐理由

  • 避免状态冲突
  • 提高可维护性
  • 减少错误
php
<?php
// 好的实践:使用状态字段
$document = [
    'status' => 'published',  // draft, published, archived, deleted
    'published_at' => new MongoDB\BSON\UTCDateTime()
];

// 不好的实践:多个布尔字段
$badDocument = [
    'is_draft' => false,
    'is_published' => true,
    'is_archived' => false,
    'is_deleted' => false
];
?>

常见问题答疑(FAQ)

问题1:布尔值应该使用true/false还是1/0?

问题描述:在MongoDB中应该使用true/false还是1/0表示布尔值?

回答内容

应该使用true/false,原因如下:

php
<?php
// 场景说明:布尔值表示方法对比

class BooleanRepresentationComparison {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    public function compareRepresentations() {
        $collection = $this->database->selectCollection('representation_comparison');
        
        // 方法1:使用布尔值(推荐)
        $collection->insertOne([
            'method' => 'boolean',
            'value' => true,
            'storage_bytes' => 2,
            'query_type' => 'is_active: true',
            'pros' => ['类型明确', '存储高效', '查询直观'],
            'cons' => []
        ]);
        
        // 方法2:使用整数
        $collection->insertOne([
            'method' => 'integer',
            'value' => 1,
            'storage_bytes' => 4,
            'query_type' => 'is_active: 1',
            'pros' => ['兼容性好'],
            'cons' => ['类型不明确', '存储较大', '查询易混淆']
        ]);
        
        // 方法3:使用字符串
        $collection->insertOne([
            'method' => 'string',
            'value' => 'true',
            'storage_bytes' => 6,
            'query_type' => 'is_active: "true"',
            'pros' => [],
            'cons' => ['类型错误', '存储最大', '查询复杂', '易出错']
        ]);
        
        return [
            'recommendation' => '使用true/false布尔值',
            'reasons' => [
                '类型安全' => '明确的布尔类型',
                '存储高效' => '仅占用2字节',
                '查询直观' => '语义清晰',
                '索引优化' => '索引效率高'
            ]
        ];
    }
}

// 使用示例
$comparison = new BooleanRepresentationComparison('testdb');
$result = $comparison->compareRepresentations();
print_r($result);
?>

问题2:如何处理布尔字段的默认值?

问题描述:布尔字段应该设置什么默认值?

回答内容

根据业务场景选择合适的默认值:

php
<?php
// 场景说明:布尔字段默认值设置

class BooleanDefaultValueHandler {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    public function demonstrateDefaultValues() {
        $collection = $this->database->selectCollection('default_values');
        
        // 场景1:用户状态(默认false,需要激活)
        $user = [
            'is_active' => false,      // 默认未激活
            'is_verified' => false,    // 默认未验证
            'is_admin' => false        // 默认非管理员
        ];
        
        // 场景2:内容设置(默认true,允许操作)
        $article = [
            'is_commentable' => true,  // 默认可评论
            'is_shareable' => true,    // 默认可分享
            'is_visible' => true       // 默认可见
        ];
        
        // 场景3:功能开关(默认false,谨慎启用)
        $feature = [
            'is_enabled' => false,     // 默认禁用
            'is_beta' => false         // 默认非测试版
        ];
        
        return [
            'user_defaults' => [
                'is_active' => false,
                'reason' => '安全考虑,需要用户主动激活'
            ],
            'content_defaults' => [
                'is_commentable' => true,
                'reason' => '用户体验,默认允许交互'
            ],
            'feature_defaults' => [
                'is_enabled' => false,
                'reason' => '风险控制,需要手动启用'
            ]
        ];
    }
    
    public function getDefaultValueGuidelines() {
        return [
            'security_first' => [
                'principle' => '安全优先',
                'examples' => [
                    'is_active' => false,
                    'is_verified' => false,
                    'is_admin' => false
                ]
            ],
            'user_experience' => [
                'principle' => '用户体验优先',
                'examples' => [
                    'is_commentable' => true,
                    'is_shareable' => true,
                    'is_visible' => true
                ]
            ],
            'risk_control' => [
                'principle' => '风险控制优先',
                'examples' => [
                    'is_enabled' => false,
                    'is_beta' => false,
                    'is_experimental' => false
                ]
            ]
        ];
    }
}

// 使用示例
$handler = new BooleanDefaultValueHandler('testdb');
$defaults = $handler->demonstrateDefaultValues();
print_r($defaults);

$guidelines = $handler->getDefaultValueGuidelines();
print_r($guidelines);
?>

问题3:如何优化布尔字段的查询性能?

问题描述:如何提高布尔字段的查询效率?

回答内容

通过索引和查询优化提高性能:

php
<?php
// 场景说明:布尔字段查询优化

class BooleanQueryOptimization {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    public function optimizeBooleanQueries() {
        $collection = $this->database->selectCollection('optimized_boolean');
        
        // 创建索引
        $collection->createIndex(['is_active' => 1]);
        $collection->createIndex(['is_active' => 1, 'created_at' => -1]);
        
        // 插入测试数据
        for ($i = 0; $i < 10000; $i++) {
            $collection->insertOne([
                'is_active' => (bool)($i % 2),
                'is_verified' => (bool)($i % 3),
                'created_at' => new MongoDB\BSON\UTCDateTime()
            ]);
        }
        
        // 优化查询1:使用索引
        $startTime = microtime(true);
        $results = $collection->find(['is_active' => true])->toArray();
        $indexedTime = microtime(true) - $startTime;
        
        // 优化查询2:复合索引
        $startTime = microtime(true);
        $results = $collection->find([
            'is_active' => true
        ], [
            'sort' => ['created_at' => -1],
            'limit' => 100
        ])->toArray();
        $compoundTime = microtime(true) - $startTime;
        
        return [
            'indexed_query' => [
                'time' => $indexedTime,
                'count' => count($results)
            ],
            'compound_query' => [
                'time' => $compoundTime,
                'count' => count($results)
            ],
            'optimization_tips' => [
                '1. 为常用布尔字段创建索引',
                '2. 使用复合索引优化排序',
                '3. 避免全表扫描',
                '4. 使用explain分析查询计划'
            ]
        ];
    }
}

// 使用示例
$optimization = new BooleanQueryOptimization('testdb');
$result = $optimization->optimizeBooleanQueries();
print_r($result);
?>

问题4:如何处理布尔字段的缺失值?

问题描述:文档中布尔字段缺失时如何处理?

回答内容

使用$exists操作符或设置默认值:

php
<?php
// 场景说明:处理布尔字段缺失值

class MissingBooleanHandler {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    public function handleMissingValues() {
        $collection = $this->database->selectCollection('missing_boolean');
        
        // 插入缺失布尔字段的文档
        $collection->insertOne([
            'name' => 'Document without boolean field'
        ]);
        
        // 插入包含布尔字段的文档
        $collection->insertOne([
            'name' => 'Document with boolean field',
            'is_active' => true
        ]);
        
        // 方法1:使用$exists检查字段是否存在
        $withField = $collection->find([
            'is_active' => ['$exists' => true]
        ])->toArray();
        
        // 方法2:使用$ifnull设置默认值
        $pipeline = [
            [
                '$project' => [
                    'name' => 1,
                    'is_active' => ['$ifNull' => ['$is_active', false]]
                ]
            ]
        ];
        
        $withDefault = $collection->aggregate($pipeline)->toArray();
        
        return [
            'documents_with_field' => count($withField),
            'documents_with_default' => count($withDefault),
            'best_practice' => '在插入文档时设置默认值,避免字段缺失'
        ];
    }
    
    public function ensureDefaultValue($document, $field, $default = false) {
        if (!isset($document[$field])) {
            $document[$field] = $default;
        }
        
        return $document;
    }
}

// 使用示例
$handler = new MissingBooleanHandler('testdb');
$result = $handler->handleMissingValues();
print_r($result);
?>

问题5:如何在聚合中使用布尔字段?

问题描述:如何在聚合管道中使用布尔字段进行统计?

回答内容

使用$cond和$sum操作符:

php
<?php
// 场景说明:聚合中使用布尔字段

class BooleanAggregation {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    public function aggregateWithBoolean() {
        $collection = $this->database->selectCollection('boolean_aggregation');
        
        // 插入测试数据
        for ($i = 0; $i < 100; $i++) {
            $collection->insertOne([
                'user_id' => $i,
                'is_active' => (bool)($i % 2),
                'is_verified' => (bool)($i % 3),
                'is_premium' => (bool)($i % 5)
            ]);
        }
        
        // 聚合统计
        $pipeline = [
            [
                '$group' => [
                    '_id' => null,
                    'total' => ['$sum' => 1],
                    'active_count' => [
                        '$sum' => ['$cond' => ['$is_active', 1, 0]]
                    ],
                    'verified_count' => [
                        '$sum' => ['$cond' => ['$is_verified', 1, 0]]
                    ],
                    'premium_count' => [
                        '$sum' => ['$cond' => ['$is_premium', 1, 0]]
                    ]
                ]
            ],
            [
                '$project' => [
                    'total' => 1,
                    'active_count' => 1,
                    'verified_count' => 1,
                    'premium_count' => 1,
                    'active_percentage' => [
                        '$multiply' => [
                            ['$divide' => ['$active_count', '$total']],
                            100
                        ]
                    ]
                ]
            ]
        ];
        
        return $collection->aggregate($pipeline)->toArray();
    }
    
    public function groupByBoolean() {
        $collection = $this->database->selectCollection('boolean_aggregation');
        
        // 按布尔字段分组
        $pipeline = [
            [
                '$group' => [
                    '_id' => '$is_active',
                    'count' => ['$sum' => 1]
                ]
            ],
            [
                '$sort' => ['_id' => 1]
            ]
        ];
        
        return $collection->aggregate($pipeline)->toArray();
    }
}

// 使用示例
$aggregation = new BooleanAggregation('testdb');
$stats = $aggregation->aggregateWithBoolean();
print_r($stats);

$grouped = $aggregation->groupByBoolean();
print_r($grouped);
?>

问题6:如何批量更新布尔字段?

问题描述:如何高效地批量更新布尔字段?

回答内容

使用updateMany或bulkWrite:

php
<?php
// 场景说明:批量更新布尔字段

class BooleanBatchUpdate {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    public function batchUpdateBooleans() {
        $collection = $this->database->selectCollection('batch_boolean');
        
        // 插入测试数据
        for ($i = 0; $i < 1000; $i++) {
            $collection->insertOne([
                'user_id' => $i,
                'is_active' => false,
                'is_verified' => false
            ]);
        }
        
        // 方法1:使用updateMany
        $startTime = microtime(true);
        $result1 = $collection->updateMany(
            ['user_id' => ['$lt' => 500]],
            ['$set' => ['is_active' => true]]
        );
        $updateManyTime = microtime(true) - $startTime;
        
        // 方法2:使用bulkWrite
        $startTime = microtime(true);
        $bulkOps = [];
        
        for ($i = 500; $i < 1000; $i++) {
            $bulkOps[] = [
                'updateOne' => [
                    ['user_id' => $i],
                    ['$set' => ['is_verified' => true]]
                ]
            ];
        }
        
        $result2 = $collection->bulkWrite($bulkOps);
        $bulkWriteTime = microtime(true) - $startTime;
        
        return [
            'updateMany' => [
                'matched' => $result1->getMatchedCount(),
                'modified' => $result1->getModifiedCount(),
                'time' => $updateManyTime
            ],
            'bulkWrite' => [
                'matched' => $result2->getMatchedCount(),
                'modified' => $result2->getModifiedCount(),
                'time' => $bulkWriteTime
            ],
            'recommendation' => '对于条件更新使用updateMany,对于复杂批量操作使用bulkWrite'
        ];
    }
}

// 使用示例
$batch = new BooleanBatchUpdate('testdb');
$result = $batch->batchUpdateBooleans();
print_r($result);
?>

实战练习

练习1:基础练习 - 用户激活系统

解题思路

  1. 创建用户文档
  2. 实现激活功能
  3. 查询激活状态

常见误区

  • 未设置默认值
  • 未创建索引
  • 未处理并发

参考代码

php
<?php
// 练习1:用户激活系统

class UserActivationExercise {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    public function run() {
        $collection = $this->database->selectCollection('exercise_users');
        $collection->drop();
        
        // 创建索引
        $collection->createIndex(['is_active' => 1]);
        
        // 步骤1:创建用户
        $result = $collection->insertOne([
            'username' => 'john_doe',
            'email' => 'john@example.com',
            'is_active' => false,
            'created_at' => new MongoDB\BSON\UTCDateTime()
        ]);
        
        $userId = $result->getInsertedId();
        echo "用户创建成功,ID: $userId\n";
        
        // 步骤2:激活用户
        $collection->updateOne(
            ['_id' => $userId],
            [
                '$set' => [
                    'is_active' => true,
                    'activated_at' => new MongoDB\BSON\UTCDateTime()
                ]
            ]
        );
        
        echo "用户已激活\n";
        
        // 步骤3:查询激活用户
        $activeUsers = $collection->find(['is_active' => true])->toArray();
        echo "激活用户数量: " . count($activeUsers) . "\n";
    }
}

// 运行练习
$exercise = new UserActivationExercise('exercise_db');
$exercise->run();
?>

练习2:进阶练习 - 权限管理系统

解题思路

  1. 设计权限结构
  2. 实现权限检查
  3. 批量权限管理

参考代码

php
<?php
// 练习2:权限管理系统

class PermissionManagementExercise {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    public function run() {
        $collection = $this->database->selectCollection('exercise_permissions');
        $collection->drop();
        
        // 步骤1:创建权限文档
        $collection->insertOne([
            'user_id' => 'user_001',
            'can_read' => true,
            'can_write' => false,
            'can_delete' => false,
            'can_admin' => false
        ]);
        
        echo "权限文档创建成功\n";
        
        // 步骤2:检查权限
        $permissions = $collection->findOne(['user_id' => 'user_001']);
        
        if ($permissions['can_read']) {
            echo "用户有读权限\n";
        }
        
        if (!$permissions['can_write']) {
            echo "用户没有写权限\n";
        }
        
        // 步骤3:授予权限
        $collection->updateOne(
            ['user_id' => 'user_001'],
            ['$set' => ['can_write' => true]]
        );
        
        echo "已授予写权限\n";
        
        // 步骤4:查询有写权限的用户
        $writers = $collection->find(['can_write' => true])->toArray();
        echo "有写权限的用户数量: " . count($writers) . "\n";
    }
}

// 运行练习
$exercise = new PermissionManagementExercise('exercise_db');
$exercise->run();
?>

练习3:挑战练习 - 功能开关系统

解题思路

  1. 设计功能开关结构
  2. 实现动态开关
  3. 支持灰度发布

参考代码

php
<?php
// 练习3:功能开关系统

class FeatureFlagExercise {
    private $database;
    
    public function __construct($databaseName) {
        $client = new MongoDB\Client("mongodb://localhost:27017");
        $this->database = $client->selectDatabase($databaseName);
    }
    
    public function run() {
        $collection = $this->database->selectCollection('exercise_features');
        $collection->drop();
        
        // 步骤1:创建功能开关
        $features = [
            ['name' => 'new_dashboard', 'is_enabled' => false],
            ['name' => 'dark_mode', 'is_enabled' => true],
            ['name' => 'beta_features', 'is_enabled' => false]
        ];
        
        $collection->insertMany($features);
        echo "功能开关创建成功\n";
        
        // 步骤2:检查功能状态
        $darkMode = $collection->findOne(['name' => 'dark_mode']);
        
        if ($darkMode['is_enabled']) {
            echo "暗黑模式已启用\n";
        }
        
        // 步骤3:启用功能
        $collection->updateOne(
            ['name' => 'new_dashboard'],
            ['$set' => ['is_enabled' => true]]
        );
        
        echo "新仪表板已启用\n";
        
        // 步骤4:查询启用的功能
        $enabledFeatures = $collection->find(['is_enabled' => true])->toArray();
        echo "启用的功能数量: " . count($enabledFeatures) . "\n";
        
        // 步骤5:批量切换
        $collection->updateMany(
            [],
            ['$set' => ['is_enabled' => false]]
        );
        
        echo "所有功能已禁用\n";
    }
}

// 运行练习
$exercise = new FeatureFlagExercise('exercise_db');
$exercise->run();
?>

知识点总结

核心要点

  1. Boolean类型特性

    • 只有两个值:true 和 false
    • 占用2字节存储空间
    • BSON类型标识符:0x08
  2. 存储机制

    • 类型标识 + 布尔值
    • 高效的存储和查询
    • 支持索引优化
  3. 命名规范

    • 使用is_、has_、can_等前缀
    • 避免否定词
    • 名称应清晰表达含义
  4. 查询优化

    • 创建索引提高性能
    • 使用复合索引优化排序
    • 避免全表扫描

易错点回顾

  1. 类型混淆

    • 使用字符串代替布尔值
    • 使用整数代替布尔值
    • 查询类型不匹配
  2. 命名不当

    • 使用否定词
    • 命名不清晰
    • 双重否定
  3. 过度使用

    • 多个布尔字段表示状态
    • 未考虑状态机
    • 维护困难

拓展参考资料

官方文档链接

进阶学习路径建议

本知识点承接:《Double类型》→《基本数据类型概述》

后续延伸至:《Null类型》→《ObjectId类型》→《Date类型》

建议学习顺序

  1. Double类型
  2. Boolean类型(本章节)
  3. Array类型
  4. Object类型
  5. Null类型