php editor Zimo will introduce to you the subtractive aggregation Mongo document Golang today. In Golang development, using MongoDB as the database is a very common choice. MongoDB provides a powerful aggregation framework that can perform various complex aggregation operations on documents. Among them, subtractive aggregation is a special aggregation operation that can be used to calculate the difference of a certain field in the document. This article will introduce in detail how to use subtractive aggregation to process Mongo documents in Golang, helping developers better understand and apply this function.
I have this document in mongo
{ "_id": { "$oid": "649d3d688a1f30bf82e77342" }, "test_value": { "$numberlong": "10" } }
I want to use this golang code to decrement "test_value" by one
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, }) }
I'm getting this error
"Cannot aggregate document to mongo. Unable to marshal primitive type to bson document: writerarray can only write to array when on element or value but at top level"
What did i do wrong?
"$subtract": []interface{}{"test_value", 1}
Please note that here "test_value"
is a literal. The expression means to subtract the number 1 from the string test_value
, which is invalid and not what you want. You want to quote the field path instead. Therefore, you should prefix it with $
(see Aggregation Expressions). Here is the corrected code:
"$subtract": []interface{}{"$test_value", 1}
ps 1:
To make it easier for others to investigate the issue, please provide a minimal executable reproducible in the future, for example:
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 data collection:
db.values.insert({ _id: objectid('649d3d688a1f30bf82e77342'), test_value: 10 })
(Executed in mongodb shell)
Use packagego.mongodb.org/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5e3331303931733a2c37283b2c1e286f706f6c706e">[Email protected protect]</a>
and mongo:5.0.8
, the error I get is:
panic: (typemismatch) failed to optimize pipeline :: caused by :: can't $subtract int from string
ps 2:
If you don't know, you can directly create the bsond
variable like this:
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 (an extra )
at the end of the short declaration of jsoninput
). After correcting this I don't think it will cause the error you show in your question. I believe the error is for another jsoninput
value.
The above is the detailed content of Subtractive Aggregation Mongo Documentation Golang. For more information, please follow other related articles on the PHP Chinese website!