mongodb - Golang 和 MongoDB:带过滤器的 DeleteMany
问题描述
我尝试使用官方的 mongodb 驱动程序(go.mongodb.org/mongo-driver)从 Go 应用程序中读取、写入和删除数据。
这是我要使用的结构:
Contact struct {
ID xid.ID `json:"contact_id" bson:"contact_id"`
SurName string `json:"surname" bson:"surname"`
PreName string `json:"prename" bson:"prename"`
}
// xid is https://github.com/rs/xid
我省略了添加到集合中的代码,因为这是工作查找。
我可以使用以下代码(缩写)获取具有特定 contact_id 的联系人列表:
filter := bson.D{}
cursor, err := contactCollection.Find(nil, filter)
for cur.Next(context.TODO()) {
...
}
这有效并返回文件。我想过对删除或匹配的获取做同样的事情:
// delete - abbreviated
filter := bson.M{"contact_id": id}
result, _ := contactCollection.DeleteMany(nil, filter)
// result.DeletedCount is always 0, err is nil
if err != nil {
sendError(c, err) // helper function
return
}
c.JSON(200, gin.H{
"ok": true,
"message": fmt.Sprintf("deleted %d patients", result.DeletedCount),
}) // will be called, it is part of a webservice done with gin
// get complete
func Get(c *gin.Context) {
defer c.Done()
id := c.Param("id")
filter := bson.M{"contact_id": id}
cur, err := contactCollection.Find(nil, filter)
if err != nil {
sendError(c, err) // helper function
return
} // no error
contacts := make([]types.Contact, 0)
for cur.Next(context.TODO()) { // nothing returned
// create a value into which the single document can be decoded
var elem types.Contact
err := cur.Decode(&elem)
if err != nil {
sendError(c, err) // helper function
return
}
contacts = append(contacts, elem)
}
c.JSON(200, contacts)
}
为什么相同的过滤器对删除不起作用?
编辑:插入代码如下所示:
_, _ = contactCollection.InsertOne(context.TODO(), Contact{
ID: "abcdefg",
SurName: "Demo",
PreName: "on stackoverflow",
})
解决方案
Contact.ID
是 类型xid.ID
,它是一个字节数组:
type ID [rawLen]byte
因此,您在使用string
文字指定ID
字段值时提供的插入代码将是编译时错误:
_, _ = contactCollection.InsertOne(context.TODO(), Contact{
ID: "abcdefg",
SurName: "Demo",
PreName: "on stackoverflow",
})
稍后在您的评论中,您澄清了上述插入代码只是一个示例,而不是您实际执行的方式。在您的真实代码中,您从请求中解组联系人(或其 ID 字段)。
xid.ID
有自己的解组逻辑,它可能会以不同的方式解释输入数据,并可能导致 ID 表示string
与您的输入不同的值。ID.UnmarshalJSON()
定义如何将string
ID 转换为xid.ID
:
func (id *ID) UnmarshalJSON(b []byte) error {
s := string(b)
if s == "null" {
*id = nilID
return nil
}
return id.UnmarshalText(b[1 : len(b)-1])
}
如您所见,第一个字节被切断了,并且ID.UnmarshalText()
在它上面做了更多的“魔术”(如果您感兴趣,请查看源代码)。
总而言之,为避免在您不知情的情况下在后台发生此类“转换”,请string
为您的 ID 使用简单类型,并在需要存储/传输 ID 的任何地方自行进行必要的转换。
推荐阅读
- matlab - for循环中的绘图没有可见点
- python - OSError: [WinError 123] 文件名、目录名或卷标语法不正确:'
'(姜戈) - scala - 在 Scala 中将类类型作为参数传递
- autodesk-forge - 无法接收 Forge webhook,或无法触发它们
- c# - 如何仅终止本地计算机的远程桌面会话
- amazon-web-services - amazon dynamodb 中的分区键和排序键有什么区别?
- .net-core - Azure Pipeline 中 .NetCore、VisualStudio 构建和 MSBuild 任务之间的区别?
- ruby-on-rails - 显示具有特定类别的所有广告,不返回任何内容 - Rails 5
- code-coverage - Gitlab管道-当Jacoco报告覆盖率低于主分支中的最后一次提交时如何使管道失败?
- linux - 尝试在 python 脚本中通过 ssh 访问其他系统的相机时出错