mongodb的查询过程

本文详细介绍了MongoDB查询过程中的关键步骤,包括语法树生成、逻辑优化、查询计划生成及执行等内容。通过深入剖析,帮助读者理解如何提高查询效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

mongodb的查询过程是一个比较复杂的过程, 从查询语句到查询计划的执行, 中间经历了如下的几个步骤:
  1. 生成语法树 (matchExpression);
  2. 逻辑优化过程:由MatchExpression 生成 CanoncalQuery;
  3. 生成查询计划: 由CanoncalQuery生成QuerySolution和 MultiPlanStage;
  4. 生成PlanExecutor;
  5. 执行计划

    查询过程的流程图:
    这里写图片描述

    生成语法树

    从一个Bson类型的filter, 生成一个MatcgExpression 树, 具体的实现可以参考: http://blog.youkuaiyun.com/baijiwei/article/details/78127191

逻辑优化过程

通过MatchExpression, 我们可以得到filter的所有的设定, 但是,这个设定可能是散乱的, 效率不高的, 逻辑优化过程的主要作用就是优化filter的设定, 使得在语义保持不变的前提下, 能够更加有效的执行。
该过程主要通过 CanonicalQuery 类来实现。
其实现细节可以参考: http://blog.youkuaiyun.com/baijiwei/article/details/78170387
该过程主要包含三个方面:
1、Normoralize tree;
2、sort tree;
3、 validate tree;

生成查询计划

通过CanonicalQuery 和MatchExpression, 类PlanEnumerator 罗列MatchExpression的各种可能的组合, (indexScan & collectionScan等), 生成具体的MatchExpression, 产生出来一个个的QueryPlan。 具体的实现在函数:QueryPlannerAccess::buildIndexedDataAccess, 生成一个树形的QuerySolutionNode树。
如果QuerySolution的个数大于1, 生成一个MultiPlanStage对象, 每个QuerySolution对应于一个PlanStage或者其子对象,planStage对象由函数StageBuilder::build 生成。
其实现细节可以参考: http://blog.youkuaiyun.com/baijiwei/article/details/78174198

生成 PlanExecutor

PlanExecutor::PlanExecutor(OperationContext* opCtx,
                           unique_ptr<WorkingSet> ws,
                           unique_ptr<PlanStage> rt,
                           unique_ptr<QuerySolution> qs,
                           unique_ptr<CanonicalQuery> cq,
                           const Collection* collection,
                           const string& ns)

如上述的代码片, 前面我们得到了PlanStage, QuerySolution以及CanonicalQuery, 可以生成一个指定的PlanExecutor, 查询计划的最终的执行是由该类的对象处理的。
生成最优的执行计划, MultiPlanStage::pickBestPlan最终选择由该函数实现, 具体的打分过程在PlanRanker::pickBestPlan.

执行查询计划

最终的执行过程非常简单: 遍历 PlanExecutor::getNextImpl

while (PlanExecutor::ADVANCED == (state = exec->getNext(&obj, NULL))) {
       WorkingSetID id = WorkingSet::INVALID_ID;
       PlanStage::StageState code = _root->work(&id);
       WorkingSetMember* member = _workingSet->get(id);
       bool hasRequestedData = true;
       ...
      if (hasRequestedData) {
          _workingSet->free(id);
          return PlanExecutor::ADVANCED;
    }
 }

这里_root 是PlanStage*, 所有的planStage的ID保存在一个list里面:
std::list results;

函数PlanStage::work就是从前往后, 得到一个个的WorkingSetID。
相关的实现细节参考: http://blog.youkuaiyun.com/baijiwei/article/details/78195766

### MongoDB 查询加密方法及实现方式 MongoDB 提供了一种称为 **Queryable Encryption** 的技术来支持查询加密的功能[^3]。这种技术允许客户端在不解密的情况下对加密的数据执行复杂的查询操作,从而增强了数据的安全性和隐私保护。 以下是关于 MongoDB 查询加密的具体方法及其实现方式: #### 1. 可查询加密的工作原理 可查询加密的核心在于能够在加密后的数据上运行查询逻辑而不需要解密原始数据。这通过一种特殊的加密算法实现,该算法能够保留某些明文属性以便于索引和匹配。此过程完全发生在客户端侧,服务器端仅接收并处理已加密的查询和数据。 #### 2. 实现步骤概述 虽然不能使用诸如“首先”这样的引导词,但为了清晰表达流程,这里按照逻辑顺序描述各部分功能: - **启用 Client-Side Field Level Encryption (CSFLE)** CSFLE 是 MongoDB 中用于字段级加密的技术之一。它依赖于 AWS KMS 或 Azure Key Vault 等外部密钥管理系统存储加密所需的主密钥。 - **配置自动加密规则** 自动加密规则定义哪些集合中的特定字段应被加密以及采用何种模式(随机化或确定性)。这些设置通常记录在一个 JSON 文件中,并由驱动程序读取应用。 - **安装必要的库和支持版本** 使用最新版官方支持的 MongoDB 驱动程序,比如 Python 的 `pymongo` 版本 >= 3.12 ,因为它们包含了对 CSFLE 和 Queryable Encryption 的原生支持[^4]。 #### 3. 示例代码展示 下面给出一段基于 PyMongo 库实现带有多关键字模糊查询的例子,尽管这不是严格意义上的加密查询演示,但它展示了如何构建灵活高效的搜索条件结构: ```python from pymongo import MongoClient import re client = MongoClient('mongodb://localhost:27017/') db = client['test_database'] collection = db['items'] keywords = ['apple', 'banana'] # 多个关键词列表 regex_patterns = [re.compile(f'.*{kw}.*') for kw in keywords] query = {'$or': [{'name': pattern} for pattern in regex_patterns]} results = collection.find(query) for result in results: print(result) ``` 上述脚本片段利用正则表达式对象创建动态匹配路径,最终组合成复合 OR 条件传递给 MongoDB 进行检索。 需要注意的是,在实际部署生产环境中之前,请务必测试整个系统的兼容性和性能表现,尤其是当引入额外层如加密时可能会带来一定开销。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值