在Go语言中使用Mgo库操作MongoDB时,查询条件的构建是核心操作之一,bson.M作为承载查询条件的核心数据结构,支持各种复杂条件的组合,尤其是嵌套条件的处理是很多开发者容易踩坑的地方。

bson.M基础概念
bson.M本质上是map[string]interface{}的别名,用来描述MongoDB的BSON文档结构,在查询场景中主要用来承载查询过滤条件。基础的等值查询可以直接通过键值对来定义,比如查询用户名为test的用户,写法如下:
package main
import (
"gopkg.in/mgo.v2/bson"
)
func main() {
// 基础等值查询条件:查询name为test的文档
query := bson.M{"name": "test"}
// 对应MongoDB查询语句:{ "name": "test" }
}
嵌套条件查询的常见场景
实际业务中经常需要处理复合条件,比如同时满足多个条件、满足多个条件中的任意一个,或者针对嵌套文档字段的查询,这些都属于嵌套条件的范畴。
1. 与条件($and)的嵌套
当需要多个条件同时满足时,可以使用$and操作符,$and的值是一个bson.M的切片,每个元素对应一个独立的条件。比如查询年龄大于18且小于30的用户:
func buildAndQuery() bson.M {
// 与条件:age > 18 且 age < 30
query := bson.M{
"$and": []bson.M{
{"age": bson.M{"$gt": 18}},
{"age": bson.M{"$lt": 30}},
},
}
// 对应MongoDB查询语句:{ "$and": [ { "age": { "$gt": 18 } }, { "age": { "$lt": 30 } } ] }
return query
}
2. 或条件($or)的嵌套
当多个条件满足任意一个即可时,使用$or操作符,结构和$and类似,同样是bson.M的切片。比如查询状态为1或者状态为2的用户:
func buildOrQuery() bson.M {
// 或条件:status为1 或者 status为2
query := bson.M{
"$or": []bson.M{
{"status": 1},
{"status": 2},
},
}
// 对应MongoDB查询语句:{ "$or": [ { "status": 1 }, { "status": 2 } ] }
return query
}
3. 嵌套文档字段查询
如果文档中存在嵌套结构,比如用户文档包含address子文档,要查询城市为北京的用户,需要通过点号连接嵌套字段名:
func buildNestedDocQuery() bson.M {
// 查询嵌套文档address下的city字段为北京的文档
query := bson.M{"address.city": "北京"}
// 对应MongoDB查询语句:{ "address.city": "北京" }
return query
}
常见错误与正确写法
很多开发者在构建复杂嵌套条件时容易犯以下错误:
- 错误1:直接在bson.M中写多个条件默认是$and,但如果是同一字段的多个条件,不能分开写,比如想写age大于18且小于30,直接写
bson.M{"age": bson.M{"$gt": 18}, "age": bson.M{"$lt": 30}}会导致后面的键值对覆盖前面的,最终只有$lt条件生效,正确写法是用$and包裹。 - 错误2:$and和$or混用时层级错误,比如想写年龄大于18,且状态为1或者2,正确的嵌套结构应该是外层是$and,其中一个条件是年龄条件,另一个条件是$or包裹的状态条件。
正确的混用示例如下:
func buildMixQuery() bson.M {
// 查询条件:age > 18 且 (status为1 或者 status为2)
query := bson.M{
"$and": []bson.M{
{"age": bson.M{"$gt": 18}},
{
"$or": []bson.M{
{"status": 1},
{"status": 2},
},
},
},
}
// 对应MongoDB查询语句:{ "$and": [ { "age": { "$gt": 18 } }, { "$or": [ { "status": 1 }, { "status": 2 } ] } ] }
return query
}
非条件($ne)的使用
当需要查询字段不等于某个值时,使用$ne操作符,属于单字段的嵌套条件,示例如下:
func buildNeQuery() bson.M {
// 查询status不等于0的用户
query := bson.M{"status": bson.M{"$ne": 0}}
// 对应MongoDB查询语句:{ "status": { "$ne": 0 } }
return query
}
总结
构建Mgo查询时,核心是先理清楚MongoDB的查询条件结构,再将结构映射到bson.M的定义中。嵌套条件的处理重点是区分不同操作符的层级,复合条件用对应的$and、$or、$ne等操作符包裹,同一字段的多个范围条件必须通过$and组合,避免键值覆盖问题。掌握这些规则后,就能快速写出正确的复杂查询条件,避免查询无效的问题。