5

I am trying to insert data that is stored in an array of struct into a MongoDB using the go.mongodb.org/mongo-driver library. My struct is

type Statement struct {
    ProductID        string `bson:"product_id" json:"product_id"`
    ModelNum         string `bson:"model_num" json:"model_num"`
    Title            string `bson:"title" json:"title"`
}

and my insertion code is

func insert(stmts []Statement) {
    client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://127.0.0.1:27017"))
    if err != nil {
        log.Fatal(err)
    }
    ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
    err = client.Connect(ctx)
    if err != nil {
        log.Fatal(err)
    }
    defer client.Disconnect(ctx)

    quickstartDatabase := client.Database("quickstart")
    testCollection := quickstartDatabase.Collection("test")
    testCollection.InsertMany(ctx, stmts) // This is giving error
}

The compiler gives the error cannot use stmts (variable of type []Statement) as []interface{} value in argument to testCollection.InsertMany at the InsertMany command.

I have tried marshalling the struct before inserting using bson.Marshal but even that doesn't work. How do I insert this data into the DB?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
khateeb
  • 5,265
  • 15
  • 58
  • 114
  • 1
    Have you tried creating a list of interface{} and cast your Statement? Something like: interfaceStmts := []interface{}{} for _, s := range stmts{ interfaceStmts = append(interfaceStmts, s) } – Mihai Feb 28 '21 at 18:06
  • @Mihai Yes, that worked. Thank you. But doesn't iterate over every element in the array? Which is the fastest way to do this? – khateeb Feb 28 '21 at 18:22
  • 1
    It does iterate over the elements in the array unfortunately. There is no nice and easy way to do the conversion. I think the good news is that the big O complexity of the code will not change with this extra iteration since the lib will also iterate over the batch so complexity is still O(n). This post https://stackoverflow.com/questions/12753805/type-converting-slices-of-interfaces/12754757#12754757 should cover the reason behind the language design. – Mihai Feb 28 '21 at 21:09

1 Answers1

3

insertMany accept []interface{}

i would make like this

newValue := make([]interface{}, len(statements))

for i := range statements {
  newValue[i] = statements[i]
}

col.InsertMany(ctx, newValue)
user8555937
  • 2,161
  • 1
  • 14
  • 39
Pocket
  • 309
  • 3
  • 11
  • 1
    Note: if you make using len(statements), then the first len(statements) records will be nil in newValue – yayayahei Apr 18 '22 at 12:44