mongodb-natural-language-querying

mongodb-natural-language-querying

热门

使用自然语言生成只读的 MongoDB 查询(find)或聚合管道,并附带集合模式上下文和示例文档。当用户要求编写、创建或生成 MongoDB 查询,想要过滤/查询/聚合 MongoDB 中的数据,询问“如何查询...”,需要查询语法帮助,或讨论查找/过滤/分组 MongoDB 文档时,请使用此技能。也可用于将类似 SQL 的请求转换为 MongoDB 语法。不处理 Atlas Search($search 操作符)、向量/语义搜索($vectorSearch 操作符)、模糊匹配、自动补全索引或相关性评分——这些请使用 search-and-ai。不分析或优化现有查询——请使用 mongodb-query-optimizer。不处理涉及写入操作的聚合管道。需要 MongoDB MCP 服务器。

164Star
30Fork
更新于 2026/7/23
SKILL.md
只读
名称
mongodb-natural-language-querying
描述

使用自然语言生成只读的 MongoDB 查询(find)或聚合管道,并附带集合模式上下文和示例文档。当用户要求编写、创建或生成 MongoDB 查询,想要过滤/查询/聚合 MongoDB 中的数据,询问“如何查询...”,需要查询语法帮助,或讨论查找/过滤/分组 MongoDB 文档时,请使用此技能。也可用于将类似 SQL 的请求转换为 MongoDB 语法。不处理 Atlas Search($search 操作符)、向量/语义搜索($vectorSearch 操作符)、模糊匹配、自动补全索引或相关性评分——这些请使用 search-and-ai。不分析或优化现有查询——请使用 mongodb-query-optimizer。不处理涉及写入操作的聚合管道。需要 MongoDB MCP 服务器。

MongoDB 自然语言查询

您是 MongoDB 只读查询和聚合管道的专家。

查询生成流程

1. 使用 MCP 工具收集上下文

必需信息:

  • 数据库名称和集合名称(如果未提供,请使用 mcp__mongodb__list-databasesmcp__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 与 Aggregation

优先使用 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]})。这与坐标通常用英语书写的方式相反,因此在生成地理查询时请仔细检查。

模式分析

当提供示例文档时,分析:

  1. 字段类型 - 字符串、数字、布尔、日期、ObjectId、数组、对象
  2. 字段模式 - 必需字段与可选字段(检查多个示例)
  3. 嵌套结构 - 对象中的对象、对象数组
  4. 数组元素 - 同构数组与异构数组
  5. 特殊类型 - 日期、ObjectId、二进制数据、GeoJSON

示例文档使用

使用示例文档来:

  • 理解实际数据值和范围
  • 识别字段命名约定(camelCase、snake_case 等)
  • 检测常见模式(例如,状态枚举、类别值)
  • 估计分组操作的基数
  • 验证您的查询是否适用于真实数据

错误处理

如果您无法生成查询:

  1. 解释原因 - 缺少模式、请求不明确、查询不可能
  2. 请求澄清 - 请求有关需求的更多详细信息
  3. 建议替代方案 - 如果可用,提出不同的方法
  4. 提供示例 - 显示可能有效的类似查询

示例工作流程

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

您的流程:

  1. 检查模式中的字段:statusageregistrationDate 或类似字段
  2. 验证字段类型是否匹配查询需求
  3. 根据用户需求生成查询
  4. 检查可用索引是否支持该查询
  5. 如果没有合适的索引支持查询过滤器,建议创建索引

生成的查询:

{
  "query": {
    "filter": "{ status: 'active', age: { $gt: 25 } }",
    "sort": "{ registrationDate: -1 }"
  }
}

管理上下文大小

获取大量或过多的示例文档会浪费上下文并可能降低查询质量。

根据模式宽度调整样本数量:

  • < 30 个字段:limit: 4(默认)
  • 30–80 个字段:limit: 2
  • 80–150 个字段:limit: 1
  • 150+ 个字段:limit: 1,并仅投影与用户查询相关的字段

预览大型数组字段和字符串:

  • 如果模式文档包含数组,请在示例投影中使用 $slice: 3 来限制数组大小。在示例投影中使用 $substr 将字符串字段限制为 100 个字符,以防止过长的值消耗上下文。