我正在try 更新我的mongo文档,但我总是收到错误,我似乎不能完全理解这个错误.

type UpdateCarpoolDTO struct {
    CarpoolID string    `json:"carpoolId" bson:"carpoolId"`
    Passenger Passenger `bson:"passenger" json:"passenger"`
}

type Passenger struct {
    User             User     `bson:"user" json:"user"`
    NumberOfSeats    int      `json:"numberOfSeats" bson:"numberOfSeats"`
    Pickup           Location `json:"pickup" bson:"pickup"`
    DropOff          Location `json:"dropOff" bson:"dropOff"`
    DoorToDoorOption bool     `bson:"doorToDoorOption" json:"doorToDoorOption"`
    LuggageSize      string   `bson:"luggageSize" json:"luggageSize"`
}

type Carpool struct {
    ID               string         `json:"id,omitempty" bson:"_id,omitempty"`
    SeatsAvailable   int            `json:"seatsAvailable" bson:"seatsAvailable"`
    Passengers       []*Passenger   `bson:"passengers" json:"passengers"`
    CreatedAt        time.Time      `json:"createdAt" bson:"createdAt"`
    UpdatedAt        time.Time      `json:"updatedAt" bson:"updatedAt"`
    ...
}

func (r *carpoolRepository) AddPassanger(dto *UpdateCarpoolDTO) (*Carpool, *errors.Error) {
    ctx, cancel := context.WithTimeout(context.Background(), mongoQueryTimeout)
    defer cancel()

    log.Println("THE DTO OBJ:::", dto)
    var result *Carpool
    filter := bson.M{"_id": dto.CarpoolID}

    update := bson.M{
        "$set": bson.M{
            "passangers": bson.M{
                "$push": dto.Passenger,
            },
            "seatsAvailable": bson.M{
                "$subtract": []interface{}{
                    "$seatsAvailable",
                    dto.Passenger.NumberOfSeats,
                },
            },
        },
        "$currentDate": bson.M{"updatedAt": true},
    }

    log.Println("THE DTO OBJ:::", "GOT HERE 1")
    options := options.FindOneAndUpdate().SetReturnDocument(1)
    log.Println("THE DTO OBJ:::", "GOT HERE 2")
    if err := r.collection.FindOneAndUpdate(ctx, filter, update, options).Decode(&result); err != nil {
        log.Println("THE DTO OBJ:::", "GOT HERE 3")
        if err == mongo.ErrNoDocuments {
            // failing here
            log.Println("THE DTO OBJ:::", "GOT HERE 4")
            return nil, errors.NewNotFoundError("request not found")
        }
        log.Println("THE DTO OBJ:::", "GOT HERE 5")
        log.Println("THE DTO OBJ 5 err:::", err.Error())
        return nil, errors.New(err.Error())
    }
    log.Println("THE DTO OBJ:::", "GOT HERE 6")
    return result, nil
}

我用来调试的LOG语句打印以下内容

THE DTO OBJ::: &{91e7a42c-xxxx {{Ebene  0x14000392c00 Obey 5120000000 <nil>} 1 {312 Main St 3 43.xxx -79.xxxx Ontario Toronto N2J 223 Canada <nil>} {978 Elm St 2 43.xxxx -80.xxx Ontario Toronto 2B2 111 Canada <nil>} true MEDIUM}} 2023/06/15 11:32:45  
THE DTO OBJ::: GOT HERE 1 2023/06/15 11:32:45  
THE DTO OBJ::: GOT HERE 2 2023/06/15 11:32:45  
THE DTO OBJ::: GOT HERE 3 2023/06/15 11:32:45  
THE DTO OBJ::: GOT HERE 5 2023/06/15 11:32:45  
THE DTO OBJ 5 err::: error decoding key seatsAvailable: cannot decode embedded document into an integer type

如有需要,可提供更多代码.

推荐答案

I put together a small example to show off the difference between a normal update (done with the method FindOneAnd更新) and an aggregate operation with the 集料 method. As a premise, I simplified a little bit the code by removing fields from the structs and hard-coding some values. If I missed something, just let me know and I'll update my answer!
First, let me share the code:

package main

import (
    "context"
    "fmt"
    "time"

    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)

type Passenger struct {
    NumberOfSeats    int    `json:"numberOfSeats" bson:"numberOfSeats"`
    DoorToDoorOption bool   `bson:"doorToDoorOption" json:"doorToDoorOption"`
    LuggageSize      string `bson:"luggageSize" json:"luggageSize"`
}

type Carpool struct {
    ID             string       `json:"id,omitempty" bson:"_id,omitempty"`
    SeatsAvailable int          `json:"seatsAvailable" bson:"seatsAvailable"`
    Passengers     []*Passenger `bson:"passengers" json:"passengers"`
    CreatedAt      time.Time    `json:"createdAt" bson:"createdAt"`
    更新dAt      time.Time    `json:"updatedAt" bson:"updatedAt"`
}

func main() {
    clientOptions := options.Client().ApplyURI("mongodb://root:root@localhost:27017")
    mongoClient, err := mongo.Connect(context.Background(), clientOptions)
    if err != nil {
        panic(err)
    }
    defer mongoClient.Disconnect(context.Background())

    appDB := mongoClient.Database("appDB")
    demoCollection := appDB.Collection("demoCollection")

    // clean up data - troubleshooting purposes
    defer func() {
        demoCollection.DeleteMany(context.Background(), bson.M{})
    }()

    // seed data
    carPool := &Carpool{
        ID:             "1",
        SeatsAvailable: 4,
        Passengers: []*Passenger{
            {NumberOfSeats: 1, DoorToDoorOption: false, LuggageSize: "small"},
        },
        CreatedAt: time.Now(),
        更新dAt: time.Now(),
    }
    insertRes, err := demoCollection.InsertOne(context.Background(), carPool)
    if err != nil {
        panic(err)
    }

    // fetch data
    fmt.Println("before update")
    cursor, err := demoCollection.Find(context.Background(), bson.M{"_id": insertRes.InsertedID})
    if err != nil {
        panic(err)
    }
    var carPools []bson.M
    if err = cursor.All(context.Background(), &carPools); err != nil {
        panic(err)
    }
    for _, v := range carPools {
        fmt.Println(v)
    }

    // set data
    filter := bson.M{"_id": insertRes.InsertedID}
    update := bson.D{
        bson.E{
            Key: "$push",
            Value: bson.D{
                bson.E{
                    Key:   "passengers",
                    Value: &Passenger{NumberOfSeats: 2, DoorToDoorOption: true, LuggageSize: "medium"},
                },
            },
        },
    }
    updateOptions := options.FindOneAnd更新().SetReturnDocument(1)
    demoCollection.FindOneAnd更新(context.Background(), filter, update, updateOptions)

    // aggregate update
    pipe := []bson.M{
        {
            "$addFields": bson.M{ // if the field already exists, it overwrites the value
                "seatsAvailable": bson.M{
                    "$subtract": []string{"$seatsAvailable", "$seatsAvailable"},
                },
            },
        },
    }
    cursor, err = demoCollection.集料(context.Background(), pipe)
    if err != nil {
        panic(err)
    }
    if err = cursor.All(context.Background(), &carPools); err != nil {
        panic(err)
    }
    fmt.Println("after update")
    for _, v := range carPools {
        fmt.Println(v)
    }
}

我将只讨论更新和聚合函数的更多细节.

更新

更新功能分为以下几个部分:

  1. 设置用于获取要更新的文档的筛选器
  2. 设置$push运算符以将项添加到集合
  3. 设置要添加的值

这里没有什么要补充的.让我们切换到聚合函数.

集料

对于此操作,您必须设置要使用的管道.这条管道用于$addFiels级.

请注意,如果您要添加已存在的字段,则此字段将被覆盖.我 Select 用这个是因为我对那个没意见.

最后,您必须设置要使用的运算符(在本例中为$subtract运算符),并提供表示要减go 的数字的字符串array.多亏了$subtract运算符,你才能从第一个中减go 第二个.

我添加了一些用于演示目的的日志(log).您可以很容易地看到记录由代码更新.

如果这有助于澄清您的问题,请让我知道,谢谢!

Mongodb相关问答推荐

如何从MongoDB集合中获取第一个和最后一个元素?

GO:如何在MongoDB中区分空字符串和nil

如何从集合中移除所有匹配的数组项?

pymongo - ifnull 重新调整整个对象而不是特定字段

Mongoose 聚合和多级组

通过insertId MongoDB获取文档

使用 AngularJs 和 MongoDB/Mongoose

使用 EventSourcing(NodeJS、MongoDB、JSON)跨多个偶尔连接的客户端同步数据

在 Mongoose 中清理用户输入

使用 MongoDB C# 驱动程序在嵌套数组上使用过滤器生成器进行查询

$lookup 结果 mongodb 的计数

Mongo Schema-less集合和 C#

如何在 Rails 中混合使用 mongodb 和传统数据库?

mongoose字符串到 ObjectID

Mongoose 版本控制:when is it safe to disable it?

获取 mongodb 中所有唯一标签的列表

Mongoose:Model.create 和 Collection.insert 有什么区别

如何在 Ubuntu 上安装 mongodb-clients 最新版本?

缩短 MongoDB 属性名称值得吗?

带有条件的MongoDB聚合查找