Mongo 过滤器在 mongo shell 中工作,但在用 go 编写时不起作用

分享于2022年07月17日 bson go mongodb 问答
【问题标题】:Mongo 过滤器在 mongo shell 中工作,但在用 go 编写时不起作用(Mongo filter works inside the mongo shell but doesn't work when written in go)
【发布时间】:2022-01-18 15:12:33
【问题描述】:

蒙哥:4.4 去:1.17.3

我正在尝试获取字符串字段值超过四个符号的文档。 这是我在 mongo 的 shell 中使用的查询:

db.player.find({
    "name": { "$exists": true },
        "$expr": { "$gt": [ { "$strLenCP": "$name" }, 4 ] } 
    })

这是相同的查询,但在 go 中编码为 bson 过滤器:

longName := bson.M{
    "name": bson.M{"$exists": true},
    "$expr": bson.M{
        "$gt": bson.A{
            bson.M{"$strLenCP": "$name"},
            4,
        },
    },
}
fmc, err := collection.Find(context.TODO(), longName)
if err != nil {
    log.Panic(err)
}
var longBoi models.Player
err = fmc.Decode(&longBoi)
if err != nil {
    log.Panic(err) 
    // panic here: 
    // 2021/12/15 15:53:46 EOF
    // panic: EOF
}

第一个将输出字符串字段值长度大于某个数字的所需文档。第二个将仅使用 EOF 、时间戳和调用堆栈出错。调试器说 batch 在游标 fmc 内不包含任何数据。

第二种情况有什么问题?

  • Find() 返回一个文档数组。解组为 []models.Player 的值,而不是单个 models.Player
  • @icza 2021/12/15 16:27:17 cannot decode document into []models.Player 不幸的是。以前不存在此错误。
  • Find() 返回 Cursor() ,而不是结果文档。你必须在光标上调用 All()

【解决方案1】:

以下解决了这个问题:

var longBoi []models.Player
err = fmc.All(context.TODO(), &longBoi)
if err != nil {
    log.Panic(err)
}

Find() 返回 Cursor() ,而不是文档。然后可以通过调用 All() 或其他方法,使用光标遍历匹配过滤器的文档。