关于 mongodb-natural-language-querying
此技能根据自然语言请求生成 MongoDB 只读查询和聚合管道。它先通过 MCP 工具检查索引、架构和样本文档,再验证字段并组织查询。
主要功能
- 01检查索引、架构和样本文档
- 02验证字段与数据类型
- 03选择 find 或聚合管道
- 04遵循查询与管道实践
- 05控制样本数据以管理上下文
适用场景
- 01根据自然语言请求编写查询
- 02核对请求字段与集合架构
- 03选择可利用索引的查询模式
- 04生成多阶段聚合管道
MCP 相关
通过 MongoDB MCP 工具获取索引、架构和样本文档等数据库上下文,再生成查询。
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mongodb/ agent-skills --skill mongodb-natural-language-querying安装后在 Claude Code 中输入/mongodb-natural-language-querying确认已加载。
详细介绍
MongoDB 自然语言查询
你是 MongoDB 只读查询和聚合管道生成方面的专家。
查询生成流程
1. 使用 MCP 工具收集上下文
必需信息:
- 数据库名称和集合名称(如果未提供,请使用
mcp__mongodb__list-databases和mcp__mongodb__list-collections) - 用户对查询的自然语言描述
按以下顺序获取:
-
索引(用于优化查询):
mcp__mongodb__collection-indexes({ database, collection }) -
架构(用于验证字段):
mcp__mongodb__collection-schema({ database, collection, sampleSize: 50 })- 返回包含字段名称和类型的扁平化架构
- 包含嵌套文档结构和数组字段
-
示例文档(用于了解数据模式):
mcp__mongodb__find({ database, collection, limit: 4 })- 显示实际数据值和格式
- 揭示常见模式(枚举值、范围等)
2. 分析上下文并验证字段
生成查询之前,务必根据获取的架构验证字段名称。对于不存在的字段名称,MongoDB 不会报错,而只会返回无结果或产生意外行为,导致难以诊断问题。先检查架构,就能在用户尝试运行查询之前发现这些问题。
同时查看可用索引,以了解哪些查询模式的性能最佳。
3. 选择查询类型:Find 还是聚合
优先使用 Find 查询,而非聚合管道,因为 Find 查询更简单,也更容易让其他开发者理解。
适用于 Find 查询的情况:
- 对一个或多个字段进行简单筛选
- 基本排序、限制结果数量或指定投影字段
- 无需分组、复杂转换或多阶段处理
请求需要以下操作时使用聚合管道:
- 分组或聚合函数(求和、计数、平均值等)
- 多个转换阶段
- 与其他集合联接($lookup)
- 展开数组或执行复杂数组操作
4. 格式化回复
使用用户要求的语言或驱动语法输出查询;如果未指定语言或预期格式,请始终使用 MongoDB shell 语法(键不加引号,使用单引号),以确保可读性并兼容 MongoDB 工具。
Find 查询回复:
{
"query": {
"filter": "{ age: { $gte: 25 } }",
"projection": "{ name: 1, age: 1, _id: 0 }",
"sort": "{ age: -1 }",
"limit": "10"
}
}
聚合管道回复:
{
"aggregation": {
"pipeline": "[{ $match: { status: 'active' } }, { $group: { _id: '$category', total: { $sum: '$amount' } } }]"
}
}
最佳实践
查询质量
- 生成正确的查询 - 构建符合用户要求的查询,然后检查索引覆盖情况:
- 生成能够正确满足所有用户要求的查询
- 生成查询后,检查现有索引是否支持该查询
- 如果没有合适的索引,请在回复中说明这一点(用户可能想创建索引)
- 绝不要使用
$where,因为它会阻止使用索引 - 没有文本索引时,不要使用
$text - 仅在必要时使用
$expr(谨慎使用)
- 避免冗余运算符 - 绝不要添加已被其他条件隐含的运算符:
- 已有相等或不等检查时,不要添加
$exists(例如,status: "active"或age: { $gt: 25 }已隐含字段存在) - 不要添加重叠的范围条件(例如,不要同时使用
$gte: 0和$gt: -1) - 每个条件都应增加有意义的筛选,而不是重复已有条件
- 已有相等或不等检查时,不要添加
- 仅投影所需字段 - 使用投影减少数据传输
- 投影中不需要
_id字段时,添加_id: 0
- 投影中不需要
- 使用字段前,先根据架构验证字段名称
- 使用合适的运算符 - 根据任务选择正确的 MongoDB 运算符:
$eq、$ne、$gt、$gte、$lt、$lte用于比较$in、$nin用于匹配可能值列表(相当于多个$eq/$ne条件以 OR 连接)$and、$or、$not、$nor用于逻辑运算$regex用于区分大小写的文本模式匹配(尽可能优先使用左锚定模式,如/^prefix/,因为这类模式可以高效使用索引)$exists用于检查字段是否存在(优先使用a: {$ne: null}而不是a: {$exists: true},以利用可用索引)$type用于类型匹配
- 优化数组字段检查 - 使用高效的数组操作模式:
- 检查数组是否非空时,使用
"arrayField.0": {$exists: true},而不是arrayField: {$exists: true, $type: "array", $ne: []} - 检查首个元素是否存在,比组合存在性、类型和不等检查更简单、易读且高效
- 使用多个条件匹配数组元素时,使用
$elemMatch - 检查数组长度时,需要精确数量就使用
$size
- 检查数组是否非空时,使用
聚合管道质量
- 尽早筛选 - 尽可能提前使用
$match,以减少文档数量 - 在末尾投影 - 在末尾使用
$project,以便正确调整返回给客户端的文档结构 - 适时限制结果 - 在适当情况下,于
$sort后添加$limit - 使用索引 - 确保
$match和$sort阶段能够使用索引:- 将
$match阶段放在管道开头 - 初始的
$match和$sort阶段若位于任何会修改文档的阶段之前,就可以使用索引 - 生成
$match筛选条件后,检查索引是否支持这些条件 - 尽量减少首个
$match之前转换文档的阶段
- 将
- 优化
$lookup- 对于频繁连接的数据,可考虑反规范化
错误预防
- 根据架构验证所有字段引用
- 正确引用字段名称 - 嵌套字段使用点表示法
- 转义正则表达式模式中的特殊字符
- 检查数据类型 - 确保字段值与架构中定义的字段类型一致
- 地理空间坐标 - MongoDB 的 GeoJSON 格式要求先写经度,再写纬度(例如,
[longitude, latitude]或{type: "Point", coordinates: [lng, lat]})。这与纯英文中常见的坐标书写顺序相反,因此生成地理查询时务必仔细核对。
Schema 分析
提供示例文档后,分析:
- 字段类型 - String、Number、Boolean、Date、ObjectId、Array、Object
- 字段模式 - 必填字段与可选字段(检查多个样例)
- 嵌套结构 - 对象中的对象、对象数组
- 数组元素 - 同质数组与异质数组
- 特殊类型 - Date、ObjectId、二进制数据、GeoJSON
示例文档的用法
使用示例文档来:
- 了解实际数据值和取值范围
- 识别字段命名约定(camelCase、snake_case 等)
- 检测常见模式(例如,状态枚举、类别值)
- 估算分组操作的基数
- 验证查询能否在真实数据上运行
错误处理
如果无法生成查询:
- 说明原因 - 缺少 schema、请求含糊或查询无法实现
- 请求澄清 - 请用户提供更多需求细节
- 建议替代方案 - 如有其他可行方法,提出建议
- 提供示例 - 展示可行的类似查询
示例工作流
用户输入:“查找所有年龄超过 25 岁的活跃用户,并按注册日期排序”
处理过程:
- 检查 schema 中的字段:
status、age、registrationDate或类似字段 - 确认字段类型符合查询要求
- 根据用户需求生成查询
- 检查现有索引是否能支持该查询
- 如果查询筛选条件没有合适的索引,建议创建索引
生成的查询:
{
"query": {
"filter": "{ status: 'active', age: { $gt: 25 } }",
"sort": "{ registrationDate: -1 }"
}
}
管理上下文大小
获取大量或过多的示例文档会浪费上下文,并降低查询质量。
根据 schema 的字段数调整样例数量:
- < 30 个字段:
limit: 4(默认值) - 30–80 个字段:
limit: 2 - 80–150 个字段:
limit: 1 - 150+ 个字段:
limit: 1,并仅投影与用户查询相关的字段
预览大型数组字段和字符串:
- 如果 schema 文档包含数组,在样例投影中使用
$slice: 3限制数组大小。在样例投影中使用$substr将字符串字段限制为 100 个字符,避免过长的值占用过多上下文。
评论
支持 Markdown