4

Lets imagine a JSON like:

"user": {
  "id": "1234",
  ...some fields,
  "achievements": [
    {
      "scope": "life achievements",
      "list": [
        {"_id": 1, "title": "some text", "gotAt": "some date"},
        {"_id": 2, "title": "some other text", "gotAt": "some date"}
      ]
    },
    {
      "scope": "sport achievements",
      "list": [
        {"_id": 1, "title": "sport", "gotAt": "some date"},
        {"_id": 2, "title": "some other sport", "gotAt": "some date"}
      ]
    },
    {
      "scope": "academic achievements",
      "list": [
        {"_id": 1, "title": "some text", "gotAt": "some date"},
        {"_id": 2, "title": "some other text", "gotAt": "some date"}
      ]
    },
  ]
}

I need to UPDATE for example the first life achievement (with id 1) using mongoDb and Golang driver Mongo-go for it

The problem is in the nesting level. I can get some array element by $ mongoDb operator, but here i need to identify every user achievement by the activity scope (life, sport, academic etc) and _id field of achievement. So I need to make a search inside an array of objects inside other array of objects.

Thats what ive done (it doesnt work anyway)

doc := coll.FindOneAndUpdate(
        context.Background(),
        bson.D{
            {"_id", "1234"},
            {"achievements.scope", "life achievements"},
            {"achievements.list._id", 1},
        },
        bson.D{
            {"$set", bson.D{
                {"achievements.$.list.$[elem].title", "some new test"},
            }},
        },
        options.FindOneAndUpdate().SetArrayFilters(options.ArrayFilters{
            Filters: append(make([]interface{}, 0), bson.D{
                {"elem", bson.D{
                    {"achievements.list._id", 1},
                }},
            }),
        }).SetReturnDocument(1),
    )

I expect this query to update only one element specified by "id" and "scope" fields. May be I use arrayFilters incorretly, or may be I set param of FindOneAndUpdate function incorrectly. Now it doesnt throw any error nor updates the document. Please help me

2 Answers 2

12

With the package go.mongodb.org/mongo-driver/mongo you can do it like this:

coll.FindOneAndUpdate(
    context.Background(),
    bson.D{
        {"id", "1234"},
        {"achievements.scope", "life achievements"},
        {"achievements.list._id", 1},
    },
    bson.M{"$set": bson.M{"achievements.$.list.$[elem].title": "some new test"}},
    options.FindOneAndUpdate().SetArrayFilters(options.ArrayFilters{
        Filters: []interface{}{bson.M{"elem._id": 1}},
    }),
)

which "translates" to shell:

db.user.findOneAndUpdate(
  {"id": "1234","achievements.scope": "life achievements","achievements.list._id": 1},
  {$set: {"achievements.$.list.$[elem].title": "some new test"}},
  {arrayFilters: [{"elem._id": 1}]}
)
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you so match! Ive combined what I have done with what you have written (specifically my array filters were incorrect). So it helped!
2

So, with help of @owlwalks, we have found the decision:

doc := coll.FindOneAndUpdate(
        context.Background(),
        bson.D{
            {"_id", "1234"},
            {"achievements.scope", "life achievements"},
        },
        bson.D{
            {"$set", bson.D{
                {"achievements.$.list.$[elem].title", "some new text"},
            }},
        },
        options.FindOneAndUpdate().SetArrayFilters(options.ArrayFilters{
            Filters: []interface{}{bson.D{
                    {"elem._id", 1},
                }},
        }).SetReturnDocument(1),
    )

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.