Go查询MongoDB需匹配驱动版本、API风格与投影写法:官方驱动须用options.Find().SetProjection()设投影,mgo需用.Select()链式调用,$text查询前必须建text索引且$filter顶层唯一。

Go 查询 MongoDB 不是“写对 filter 就完事”,关键在驱动版本、API 风格、投影写法三者是否匹配。用错驱动或混用语法,Find() 会静默返回空结果,或报 invalid operator 错误——这不是数据问题,是调用路径错了。
用官方驱动时,projection 必须用 options.Find().SetProjection()
官方驱动 go.mongodb.org/mongo-driver/mongo 不接受 Find() 的第二个参数作为投影。把 bson.M{"name": 0} 直接塞进 Find(ctx, filter, projection) 会编译失败或 panic。
-
Find()只接收两个参数:context.Context和filter interface{} - 投影必须显式传入
options.Find()并用SetProjection()设置 -
_id字段默认返回,如需隐藏,必须在 projection 中写"_id": 0 - 示例写法:
opts := options.Find().SetProjection(bson.M{"name": 0, "email": 0}) cursor, err := collection.Find(ctx, bson.M{"age": bson.M{"$gt": 18}}, opts)
用 mgo 驱动时,投影必须走 .Select() 链式调用
mgo(gopkg.in/mgo.v2)不支持把 projection 当作 Find() 的第二个参数。写成 col.Find(bson.M{}, bson.M{"name": 0}) 实际被解析为 $and 查询,{"name": 0} 被当作文档字段匹配条件,导致只返回 name: false 或 name: null 的文档。
-
Find()参数只能是单个interface{},通常为bson.M或nil - 排除字段必须调用
.Select(bson.M{"field": 0}),多个字段就写bson.M{"a": 0, "b": 0} - 不能混用
1和0(_id除外),否则报错 - 正确写法:
err := col.Find(nil).Select(bson.M{"name": 0, "_id": 0}).All(&results)
$text 查询前必须先建 text index,且 filter 写法固定
文本搜索不是加个 $text 就能跑。没建索引直接查,会报 text index required;建了索引但 $search 写错位置,查不到任何结果。
- 必须先对目标字段(如
description)创建 text index:model := mongo.IndexModel{Keys: bson.D{{"description", "text"}}} _, err := collection.Indexes().CreateOne(ctx, model) - 查询时
$text必须在顶层 filter 中,且只允许一个$text表达式 - 正确写法:
filter := bson.M{"$text": bson.M{"$search": "vegetarian curry"}} cursor, _ := collection.Find(ctx, filter) -
$search值支持短语(加双引号)、布尔操作符(AND/OR),但大小写敏感,且不支持通配符
最常被忽略的一点:mgo 已归档,官方驱动的 SetProjection() 和 FindOptions 是强制路径,没有替代写法。别试图“简化”成一行带两个 map 的调用——那只会让错误延迟到运行时才暴露。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











