2

Based on the documentation, go.mongodb.org/mongo-driver doesn't seem to provide a way to auto-increment ID when it is upserting a document that has not provided an ID.

    type Document struct {
        ID             int    `bson:"_id"`
        Foo            string `bson:"foo"`
    }

    document := &Document{Foo: "test"}

    filter := bson.M{"_id": bson.M{"$eq": document.ID}}
    update := bson.M{"$set": document}

    res, err := mongoClient.Database(dbName).
        Collection(collectionName).
        UpdateOne(ctx, filter, update,
            options.Update().SetUpsert(true))

In the code example above, ID will be defaulted to the zero value of int, which is 0, and will be persisted in MongoDB as {"_id":0,"foo":"test"}.

Is there a clean way for auto-incrementing ID when ID is not provided using mongo-driver, without doing the logic of tracking the last ID myself? Say for example there are already 5 documents in the DB, then running the code above will persist {"_id":6,"foo":"test"} when ID is not provided.

Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63
gogofan
  • 533
  • 1
  • 10
  • 20
  • If you are not dependent on the increment of values itself, Use a UUID for uniqueness. Its very common in go. – diyoda_ Apr 07 '20 at 12:23
  • The autocremented ID's are actually very important for backward compatibility, but can't find a good solution with `go.mongodb.org/mongo-driver` without implementing much logic myself. – gogofan Apr 07 '20 at 17:16
  • Is there a reason why you don't want to use the default ObjectID ? – Wan B. Apr 14 '20 at 01:22

2 Answers2

3

I found the same problem, the solution that i thought was to define the Document struct without ID:

type Document struct {
    Foo string `bson:"foo"`
}

Then, if an InsertOne operation is executed using the mongo-driver:

res, err := mongoClient.Database(dbName).Collection(collectionName).InsertOne(ctx, document)

The _id will be created automatically in the database(You can repeat the InsertOne operation several times and new _ids will appear).

The mongodb documentation explains this behaviour: "If the document does not specify an _id field, then mongod will add the _id field and assign a unique ObjectId for the document before inserting." (You can read more details in https://docs.mongodb.com/manual/reference/method/db.collection.insertOne/#db.collection.insertOne)

In case that you need the new created _id for some reason, you can use the following snippet as a reference to retrieve it:

fmt.Println("New Document created with mongodb _id: " + res.InsertedID.(primitive.ObjectID).Hex())

(primitive.ObjectID is related with this: import "go.mongodb.org/mongo-driver/bson/primitive")

Hope this helps!

Nelson
  • 233
  • 1
  • 4
  • 6
3

You can also do the following:

    type Document struct {
        ID             int    `bson:"_id,omitempty"`
        Foo            string `bson:"foo"`
    }