Abhishek Soni
Abhishek Soni

Reputation: 1827

Golang Mongo Insert with self generated _Id using bson.NewObjectID() resulting in unexpected schema

Hi i am using mongo and golang according to my use case i want to generate a _id before insertion, for that i am using

 bson.NewobjectId()

my struct is somewhat like this

type Device struct {
    Id             bson.ObjectId `bson:"_id" json:"_id,omitempty"`
    UserId         string        `bson:"userId" json:"userId"`
    CategorySlug   string        `bson:"categorySlug" json:"categorySlug"`
    CreatedAt      time.Time     `bson:"createdAt" json:"createdAt"`
    ModifiedAt     time.Time     `bson:"modifiedAt" json:"modifiedAt"`
    BrandId        int           `bson:"brandId" json:"brandId"`
    Category       string        `bson:"category" json:"category"`
}

when i am using this json request

{
    "userId" : "gKn42jJD8uy8ksQpi",
    "categorySlug" : "television",
    "createdAt" : "2016-08-25T18:47:29.558Z",
    "modifiedAt" : "2016-08-25T18:47:29.558Z",
    "brandId" : 90,
    "category" : "LED TV",
    "dateOfPurchase" : "2016-08-25T18:47:29.558Z"
}

and decodes this into device type and after that initialize my id using decode.ID = bson.NewObjectId()

but when i looked into my database the inserted value its strangely in this form

{
    "_id" : ObjectId("57bf425a34ce5ee85891b914"),
    "0" : {
        "_id" : ObjectId("57bf425ae03ec2179a000001"),
        "userId" : "gKn42jJD8uy8ksQpi",
        "categorySlug" : "television",
        "createdAt" : ISODate("2016-08-25T18:47:29.558Z"),
        "modifiedAt" : ISODate("2016-08-25T18:47:29.558Z"),
        "brandId" : 90,
        "category" : "LED TV",
        "dateofpurchase" : ISODate("2016-08-25T18:47:29.558Z")
    }
}

I dont know the reason why is this happening so i want my data in a proper mongo document . Please help me let know why is this thing happening and new _id is getting generated

Upvotes: 4

Views: 22512

Answers (3)

popstr
popstr

Reputation: 1110

If you are like me and you want mongodb to create the _id for you, you can use a pointer and omitempty like this:

type MyDocument struct {
    ID      *primitive.ObjectID `bson:"_id,omitempty"`
    Name    string              `bson:"name"`
}

Then just create a new instance of the struct and insert it to the db. You will get the generated ID back in the result object.

doc := MyDocument{
    Name: "This is the name",
}
insertResult, err := db.collection.InsertOne(ctx, doc)
if err != nil {
    // handle
}
insertedID := insertResult.InsertedID.(primitive.ObjectID)

To fetch the created document, you do like this:

findResult := db.collection.FindOne(ctx, bson.M{"_id": insertedID})
insertedDoc := MyDocument{}
err = findResult.Decode(&insertedDoc)
if err != nil {
    // handle
}

Good luck!

Upvotes: 0

Muhammad Tariq
Muhammad Tariq

Reputation: 4654

The new and recommended approach of generating mongodb _id is using primitive.ObjectID. Below is a simple example


import "go.mongodb.org/mongo-driver/bson/primitive"

type Post struct {
    ID        primitive.ObjectID `bson:"_id"`
    Title     string             `bson:"title"`
    Body      string             `bson:"body"`
    Tags      []string           `bson:"tags"`
    Comments  uint64             `bson:"comments"`
    CreatedAt time.Time          `bson:"created_at"`
    UpdatedAt time.Time          `bson:"updated_at"`
}

To insert a new document you will use primitive.NewObjectID()

_, err := col.InsertOne(ctx, &Post{
    ID:        primitive.NewObjectID(),
    Title:     "post",
    Tags:      []string{"mongodb"},
    Body:      `blog post`,
    CreatedAt: time.Now(),
}) 

and here is the insert result

{
    "_id" : ObjectId("5c71f03ccfee587e4212ad90"),
    "title" : "post",
    "body" : "blog post",
    "tags" : [ 
        "mongodb"
    ],
    "comments" : NumberLong(0),
    "created_at" : ISODate("2019-02-24T01:15:40.329Z"),
    "updated_at" : null
}

Above code is taken from this article: https://vkt.sh/go-mongodb-driver-cookbook/

Upvotes: 14

CrazyCrow
CrazyCrow

Reputation: 4235

I'm pretty sure it's something with your other code. Next code (that uses your data structure) correctly inserts single entries.

package main

import (
    "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
    "time"
)

type Device struct {
    Id           bson.ObjectId `bson:"_id" json:"_id,omitempty"`
    UserId       string        `bson:"userId" json:"userId"`
    CategorySlug string        `bson:"categorySlug" json:"categorySlug"`
    CreatedAt    time.Time     `bson:"createdAt" json:"createdAt"`
    ModifiedAt   time.Time     `bson:"modifiedAt" json:"modifiedAt"`
    BrandId      int           `bson:"brandId" json:"brandId"`
    Category     string        `bson:"category" json:"category"`
}

func main() {
    session, err := mgo.Dial("mongodb://127.0.0.1:27017/so")

    if err != nil {
        panic(err)
    }
    defer session.Close()
    session.SetMode(mgo.Monotonic, true)

    c := session.DB("so").C("insrt")

    doc := Device{
        Id:           bson.NewObjectId(),
        UserId:       "gKn42jJD8uy8ksQpi",
        CategorySlug: "television",
        CreatedAt:    time.Now(),
        ModifiedAt:   time.Now(),
        BrandId:      90,
        Category:     "LED TV",
    }

    err = c.Insert(doc)
    if err != nil {
        panic(err)
    }
}

Upvotes: 3

Related Questions