我有一份Mongo 版的文件

{
  "_id": {
    "$oid": "649d3d688a1f30bf82e77342"
  },
  "test_value": {
    "$numberLong": "10"
  }
}

我想用这个Golang代码将"test_value"减go 一

    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,
        })
    }

我得到了这个错误

"无法将文档聚合到Mongo.无法封送类型原语.A到BSON文档:Write数组只能在定位在元素或值上时写入数组,但定位在TopLevel上"

我做错什么了?

推荐答案

"$subtract": []interface{}{"test_value", 1}

请注意,这里的"test_value"是字面意思.表达式的意思是从字符串test_value中减go 数字1,这是无效的,也不是您想要的.您希望改为引用字段路径.因此,您应该在其前面加上$(参见aggregation expressions).以下是更正后的代码:

"$subtract": []interface{}{"$test_value", 1}

PS 1:

为了方便其他人调查这个问题,请在future 提供一个最小的可执行复制器,例如:

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.0mongo: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的值.

Mongodb相关问答推荐

MongoDB通过查找具有多个数组的对象进行聚合

如何在 MongoDB 中的集合下查找同一文档

发布到 MongoDB 时生成的附加id字段

Mongo按最大分组排序

数组过滤器 MongoDB

mongo如何通过聚合加载嵌套文档

判断对象数组中的值是否存在golang

对 MongoDB 集合中的对象数组进行排序

mongoDB 过滤、排序和排名结果

映射数组导致 mongodb 聚合

在 mongodb 聚合中的阶段之后输出具有序列数字 id 的新集合

MongoDb c# driver LINQ vs Native 查询

如何在 Mongo 聚合中合并文档中的数组字段

使用 ObjectId.GenerateNewId() 还是离开 MongoDB 创建一个?

使用管道聚合的 Spring Data MongoDB 查找

有没有办法为 mongoose.js 聚合提供 allowDiskUse 选项?

带有排序功能的mongoose findOne

无法从 MongoDb C# 中的 BsonType ObjectId 反序列化字符串

从每个组中 Select 前 N 行

MongoDB 中的多个 $inc 更新