英文:
Subtraction Aggregate Mongo Document Golang
问题
我已经将您提供的内容翻译成中文,如下所示:
我在Mongo中有这个文档:
{
"_id": {
"$oid": "649d3d688a1f30bf82e77342"
},
"test_value": {
"$numberLong": "10"
}
}
我想用以下的Golang代码将"test_value"减去一:
jsonInput := []map[string]interface{}{
{
"$match": map[string]interface{}{
"test_value": 10,
},
},
{
"$set": map[string]interface{}{
"test_value": map[string]interface{}{
"$subtract": []interface{}{"test_value", 1}},
},
},
})
value, bsonByte, errMarshal := bson.MarshalValue(jsonInput)
if errMarshal != nil {
modules.DoLog("ERROR", "", "MongoService", "aggregateDocument", "无法将jsonInput转换为BSONByte", true, errMarshal)
ctx.IndentedJSON(200, gin.H{
"error": errMarshal.Error(),
})
return
}
fmt.Println(value)
bsonD := bson.A{}
errUnmarshal1 := bson.UnmarshalValue(value, bsonByte, &bsonD)
if errUnmarshal1 != nil {
modules.DoLog("ERROR", "", "MongoService", "aggregateDocument", "无法将BSONByte转换为BSOND", true, errUnmarshal1)
ctx.IndentedJSON(200, gin.H{
"error": errUnmarshal1.Error(),
})
return
}
_, err := Client.Database("rhanov_queries").Collection(collectionName).Aggregate(ContextMongo, bsonD)
if err != nil {
modules.DoLog("ERROR", "", "MongoService", "aggregateDocument", "无法将文档聚合到Mongo", true, err)
ctx.IndentedJSON(200, gin.H{
"error": err,
})
}
然后我得到了这个错误:
"无法将文档聚合到Mongo。无法将类型primitive.A编组为BSON文档:WriteArray只能在元素或值上定位时写入数组,但当前定位在顶层"
我做错了什么?
英文:
i have this document in mongo
{
"_id": {
"$oid": "649d3d688a1f30bf82e77342"
},
"test_value": {
"$numberLong": "10"
}
}
i want to subtract "test_value" by one with this golang code
jsonInput := []map[string]interface{}{
{
"$match": map[string]interface{}{
"test_value": 10,
},
},
{
"$set": map[string]interface{}{
"test_value": map[string]interface{}{
"$subtract": []interface{}{"test_value", 1}},
},
},
})
value, bsonByte, errMarshal := bson.MarshalValue(jsonInput)
if errMarshal != nil {
modules.DoLog("ERROR", "", "MongoService", "aggregateDocument", "cannot Marshal jsonInput to BSONByte", true, errMarshal)
ctx.IndentedJSON(200, gin.H{
"error": errMarshal.Error(),
})
return
}
fmt.Println(value)
bsonD := bson.A{}
errUnmarshal1 := bson.UnmarshalValue(value, bsonByte, &bsonD)
if errUnmarshal1 != nil {
modules.DoLog("ERROR", "", "MongoService", "aggregateDocument", "cannot Unmarshal BSONByte to BSOND", true, errUnmarshal1)
ctx.IndentedJSON(200, gin.H{
"error": errUnmarshal1.Error(),
})
return
}
_, err := Client.Database("rhanov_queries").Collection(collectionName).Aggregate(ContextMongo, bsonD)
if err != nil {
modules.DoLog("ERROR", "", "MongoService", "aggregateDocument", "cannot aggregate document to Mongo", true, err)
ctx.IndentedJSON(200, gin.H{
"error": err,
})
}
and i get this error
"cannot aggregate document to Mongo. cannot marshal type primitive.A to a BSON Document: WriteArray can only write a Array while positioned on a Element or Value but is positioned on a TopLevel"
what did i do wrong?
答案1
得分: 1
"$subtract": []interface{}{"test_value", 1}
请注意,这里的"test_value"
是一个字面量。该表达式的意思是从字符串test_value
中减去数字1,这是无效的,也不是你想要的。你想要引用字段路径。所以你应该在它前面加上$
(参见聚合表达式)。以下是修正后的代码:
"$subtract": []interface{}{"$test_value", 1}
PS 1:
为了方便其他人查看问题,请在以后提供一个最小可执行的重现示例,例如:
package main
import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
jsonInput := []map[string]interface{}{
{
"$match": map[string]interface{}{
"test_value": 10,
},
},
{
"$set": map[string]interface{}{
"test_value": map[string]interface{}{
"$subtract": []interface{}{"test_value", 1},
// `test_value` should be prefixed with $ like this:
// "$subtract": []interface{}{"$test_value", 1},
},
},
},
}
typ, buf, err := bson.MarshalValue(jsonInput)
if err != nil {
panic(err)
}
fmt.Println(typ)
var bsonD bson.A
if err := bson.UnmarshalValue(typ, buf, &bsonD); err != nil {
panic(err)
}
client, err := mongo.Connect(context.Background(), options.Client().ApplyURI("mongodb://localhost"))
if err != nil {
panic(err)
}
collection := client.Database("demo").Collection("values")
cur, err := collection.Aggregate(context.Background(), bsonD)
if err != nil {
panic(err)
}
defer cur.Close(context.Background())
for cur.Next(context.Background()) {
fmt.Printf("%+v", cur.Current)
}
}
并使用以下方式初始化集合数据:
db.values.insert({ _id: ObjectId('649d3d688a1f30bf82e77342'), test_value: 10 })
(在MongoDB Shell中执行)
使用go.mongodb.org/mongo-driver@v1.12.0
和mongo:5.0.8
包,我得到的错误是:
panic: (TypeMismatch) Failed to optimize pipeline :: caused by :: can't $subtract int from string
PS 2:
如果你不知道,你可以直接这样创建bsonD
变量:
bsonD := bson.A{
bson.M{
"$match": bson.M{
"test_value": 10,
},
},
bson.M{
"$set": bson.M{
"test_value": bson.M{
"$subtract": bson.A{"$test_value", 1},
},
},
},
}
PS 3:
你展示的代码有一个语法错误(jsonInput
的短声明结尾有一个多余的)
)。纠正这个错误后,我不认为它会导致你在问题中展示的错误。我相信错误是由另一个jsonInput
值引起的。
英文:
"$subtract": []interface{}{"test_value", 1}
Please note that here "test_value"
is a literal. The expression means subtract the number 1 from the string test_value
, which is invalid and is not what you want. You want to refer to the field path instead. So you should prefix it with $
(see aggregation expressions). Here is the corrected code:
"$subtract": []interface{}{"$test_value", 1}
PS 1:
To make it easy for others to look into the issue, please provide a minimal executable reproducer in the future, such as:
package main
import (
"context"
"fmt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
func main() {
jsonInput := []map[string]interface{}{
{
"$match": map[string]interface{}{
"test_value": 10,
},
},
{
"$set": map[string]interface{}{
"test_value": map[string]interface{}{
"$subtract": []interface{}{"test_value", 1},
// `test_value` should be prefixed with $ like this:
// "$subtract": []interface{}{"$test_value", 1},
},
},
},
}
typ, buf, err := bson.MarshalValue(jsonInput)
if err != nil {
panic(err)
}
fmt.Println(typ)
var bsonD bson.A
if err := bson.UnmarshalValue(typ, buf, &bsonD); err != nil {
panic(err)
}
client, err := mongo.Connect(context.Background(), options.Client().ApplyURI("mongodb://localhost"))
if err != nil {
panic(err)
}
collection := client.Database("demo").Collection("values")
cur, err := collection.Aggregate(context.Background(), bsonD)
if err != nil {
panic(err)
}
defer cur.Close(context.Background())
for cur.Next(context.Background()) {
fmt.Printf("%+v", cur.Current)
}
}
And initialize the collection data with:
db.values.insert({ _id: ObjectId('649d3d688a1f30bf82e77342'), test_value: 10 })
(executed in MongoDB Shell)
With the package go.mongodb.org/mongo-driver@v1.12.0
and mongo:5.0.8
, the error I got is:
panic: (TypeMismatch) Failed to optimize pipeline :: caused by :: can't $subtract int from string
PS 2:
In case you don't know, you can create the bsonD
variable like this directly:
bsonD := bson.A{
bson.M{
"$match": bson.M{
"test_value": 10,
},
},
bson.M{
"$set": bson.M{
"test_value": bson.M{
"$subtract": bson.A{"$test_value", 1},
},
},
},
}
PS 3:
The code you show has a syntax error (the end of the short declaration of jsonInput
has an extra )
). After correcting this error, I don't think it can cause the error you show in your question. I believe the error is for another jsonInput
value.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论