mcpField
M
mongodb-natural-language-querying

mongodb-natural-language-querying

github.com/mongodb数据与数据库1924.7k 次安装1 周前更新
代码仓库

关于 mongodb-natural-language-querying

此技能根据自然语言请求生成 MongoDB 只读查询和聚合管道。它先通过 MCP 工具检查索引、架构和样本文档,再验证字段并组织查询。

主要功能

  1. 01检查索引、架构和样本文档
  2. 02验证字段与数据类型
  3. 03选择 find 或聚合管道
  4. 04遵循查询与管道实践
  5. 05控制样本数据以管理上下文

适用场景

  1. 01根据自然语言请求编写查询
  2. 02核对请求字段与集合架构
  3. 03选择可利用索引的查询模式
  4. 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)
  • 用户对查询的自然语言描述

按以下顺序获取:

  1. 索引(用于优化查询):

    mcp__mongodb__collection-indexes({ database, collection })
    
  2. 架构(用于验证字段):

    mcp__mongodb__collection-schema({ database, collection, sampleSize: 50 })
    
    • 返回包含字段名称和类型的扁平化架构
    • 包含嵌套文档结构和数组字段
  3. 示例文档(用于了解数据模式):

    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' } } }]"
  }
}

最佳实践

查询质量
  1. 生成正确的查询 - 构建符合用户要求的查询,然后检查索引覆盖情况:
    • 生成能够正确满足所有用户要求的查询
    • 生成查询后,检查现有索引是否支持该查询
    • 如果没有合适的索引,请在回复中说明这一点(用户可能想创建索引)
    • 绝不要使用 $where,因为它会阻止使用索引
    • 没有文本索引时,不要使用 $text
    • 仅在必要时使用 $expr(谨慎使用)
  2. 避免冗余运算符 - 绝不要添加已被其他条件隐含的运算符:
    • 已有相等或不等检查时,不要添加 $exists(例如,status: "active" 或 age: { $gt: 25 } 已隐含字段存在)
    • 不要添加重叠的范围条件(例如,不要同时使用 $gte: 0 和 $gt: -1)
    • 每个条件都应增加有意义的筛选,而不是重复已有条件
  3. 仅投影所需字段 - 使用投影减少数据传输
    • 投影中不需要 _id 字段时,添加 _id: 0
  4. 使用字段前,先根据架构验证字段名称
  5. 使用合适的运算符 - 根据任务选择正确的 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 用于类型匹配
  6. 优化数组字段检查 - 使用高效的数组操作模式:
    • 检查数组是否非空时,使用 "arrayField.0": {$exists: true},而不是 arrayField: {$exists: true, $type: "array", $ne: []}
    • 检查首个元素是否存在,比组合存在性、类型和不等检查更简单、易读且高效
    • 使用多个条件匹配数组元素时,使用 $elemMatch
    • 检查数组长度时,需要精确数量就使用 $size
聚合管道质量
  1. 尽早筛选 - 尽可能提前使用 $match,以减少文档数量
  2. 在末尾投影 - 在末尾使用 $project,以便正确调整返回给客户端的文档结构
  3. 适时限制结果 - 在适当情况下,于 $sort 后添加 $limit
  4. 使用索引 - 确保 $match 和 $sort 阶段能够使用索引:
    • 将 $match 阶段放在管道开头
    • 初始的 $match 和 $sort 阶段若位于任何会修改文档的阶段之前,就可以使用索引
    • 生成 $match 筛选条件后,检查索引是否支持这些条件
    • 尽量减少首个 $match 之前转换文档的阶段
  5. 优化 $lookup - 对于频繁连接的数据,可考虑反规范化
错误预防
  1. 根据架构验证所有字段引用
  2. 正确引用字段名称 - 嵌套字段使用点表示法
  3. 转义正则表达式模式中的特殊字符
  4. 检查数据类型 - 确保字段值与架构中定义的字段类型一致
  5. 地理空间坐标 - MongoDB 的 GeoJSON 格式要求先写经度,再写纬度(例如,[longitude, latitude] 或 {type: "Point", coordinates: [lng, lat]})。这与纯英文中常见的坐标书写顺序相反,因此生成地理查询时务必仔细核对。

Schema 分析

提供示例文档后,分析:

  1. 字段类型 - String、Number、Boolean、Date、ObjectId、Array、Object
  2. 字段模式 - 必填字段与可选字段(检查多个样例)
  3. 嵌套结构 - 对象中的对象、对象数组
  4. 数组元素 - 同质数组与异质数组
  5. 特殊类型 - Date、ObjectId、二进制数据、GeoJSON

示例文档的用法

使用示例文档来:

  • 了解实际数据值和取值范围
  • 识别字段命名约定(camelCase、snake_case 等)
  • 检测常见模式(例如,状态枚举、类别值)
  • 估算分组操作的基数
  • 验证查询能否在真实数据上运行

错误处理

如果无法生成查询:

  1. 说明原因 - 缺少 schema、请求含糊或查询无法实现
  2. 请求澄清 - 请用户提供更多需求细节
  3. 建议替代方案 - 如有其他可行方法,提出建议
  4. 提供示例 - 展示可行的类似查询

示例工作流

用户输入:“查找所有年龄超过 25 岁的活跃用户,并按注册日期排序”

处理过程:

  1. 检查 schema 中的字段:status、age、registrationDate 或类似字段
  2. 确认字段类型符合查询要求
  3. 根据用户需求生成查询
  4. 检查现有索引是否能支持该查询
  5. 如果查询筛选条件没有合适的索引,建议创建索引

生成的查询:

{
  "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