mongodb 检查对象数组中的值是否存在

f0brbegy  于 2022-12-03  发布在  Go
关注(0)|答案(1)|浏览(178)

我试图在附加新值之前检查mongo数据库上是否存在值,但每次都出现错误。

obId, _ := primitive.ObjectIDFromHex(id)
        query := bson.D{{Key: "_id", Value: obId}}
    
        var result bson.M
        er := r.collection.FindOne(ctx, bson.M{"_id": obId, "statusData.status": bson.M{"$in": []string{string(p.Status)}}}).Decode(&result)
        if er != nil {
            if er == mongo.ErrNoDocuments {
                return nil, errors.New(fmt.Sprintf("ERR NA  %v, %v", er.Error(), p.Status))
            }
            return nil, errors.New(fmt.Sprintf("ERR NORR  %v", er.Error()))
        }

doc, err := utils.ToDoc(p)
    if err != nil {
        return nil, errors.New(err.Error())
    }

    update := bson.D{{Key: "$set", Value: doc}}
    res := r.collection.FindOneAndUpdate(ctx, query, update, options.FindOneAndUpdate().SetReturnDocument(1))

我的文档如下所示

{
  "statusData": [
                {
                    "status": "new",
                    "message": "You created a new dispatch request",
                    "createdAt": "1657337212751",
                    "updatedAt": null
                },
                {
                    "status": "assigned",
                    "message": "Justin has been assigned to you",
                    "createdAt": "1657412029130",
                    "updatedAt": null,
                    "_id": "62ca19bdf7d864001cabfa4a"
                }
            ],
            "createdAt": "2022-07-10T00:09:01.785Z",

......)
有不同的状态,我想确保在用新值更新数据库之前,相同的状态没有被多次发送到数据库。

type StatusType string

const (
    NEW              StatusType = "new"
    ACKNOWLEDGED     StatusType = "acknowledged"
    ASSIGNED         StatusType = "assigned"
    REJECT           StatusType = "rejected"
    CANCEL           StatusType = "cancelled"
    COMPLETE         StatusType = "completed"
)

utils.ToDoc

func ToDoc(v interface{}) (doc *bson.D, err error) {
    data, err := bson.Marshal(v)
    if err != nil {
        return
    }

    err = bson.Unmarshal(data, &doc)
    return
}

已尝试更新

filter := bson.M{
        "_id":               obId,
        "statusData.status": bson.M{"$ne": p.Status},
    }
    update := bson.M{
        "$push": bson.M{
            "statusData": newStatusToAdd,
        },
        "$set": bson.D{{Key: "$set", Value: doc}},
    }

    result, err := r.collection.UpdateOne(ctx, filter, update)
    if err != nil {
        // Handle error
        return nil, errors.New(err.Error())
    }
    if result.MatchedCount == 0 {
        // The status already exists in statusData
    } else if result.ModifiedCount == 1 {
        // new status was added successfuly
    }

返回错误
“写入异常:写入错误:[在更新的替换文档的上下文中,不允许“$set”中以美元($)为前缀的字段“$set”。请考虑使用带有$replaceWith的聚合管道。]”

eoigrqb6

eoigrqb61#

使用筛选器,该筛选器还排除具有要添加的状态的文档。如果阵列中已存在该状态,则此筛选器将不匹配任何文档。仅当尚未添加该状态时,才会执行更新操作:

var newStatusToAdd = ... // This is the new statusData document you want to add

filter := bson.M{
    "_id": obId,
    "statusData.status": bson.M{"$ne": p.Status},
}
update := bson.M{
    "$push": bson.M{
        "statusData": newStatusToAdd,
    },
    "$set": doc,
}

result, err := r.collection.UpdateOne(ctx, filter, update)
if err != nil {
    // Handle error
    return
}
if result.MatchedCount == 0 {
    // The status already exists in statusData
} else if result.ModifiedCount == 1 {
    // new status was added successfuly
}

相关问题