wgp
wgp

Reputation: 1157

How to insert array of objects into MongoDB using Go

I have JSON from an API that I want to save to MongoDB using the mgo package. My JSON looks like this:

{
  "something": "value"
  "collection": [
    { "obj1": "value" }
    // ... (Variable number of objects here)
  ]
}

To save this data I've created a new type in my Go application that looks like this:

type MyData struct {
  Something string
  Collection []string // This actually contains more than strings but I'll be happy if I can just get strings saved
}

mongoSess, err := mgo.Dial("localhost:27017")
if err != nil {
  panic(err)
}
defer mongoSess.Close()

c := mongoSess.DB("mydatabase").C("mycollection")
insertErr := c.Insert(&MyData{something, collection})

This code works but the problem is that it isn't saving anything in my collection field which should be an array of JSON objects. Nothing at all. I get the keys in my database and they are the right type but they have no data. Here's what the Mongo output is:

{ "_id" : ObjectId("5520c535a236d8a9a215d096"), "something" : "value", "collection" : [ ] }

Can anyone spot what it is I'm doing wrong? I'm obviously new to Go and having trouble with types.

Solution

The answers here really helped me a lot. I'm at fault for not properly explaining things as the answers sent me on the right track but didn't solve the issue directly. Here's what the actual solution is.

package main

import (
  "encoding/json"
  "github.com/bitly/go-simplejson"
  "gopkg.in/mgo.v2"
  //"gopkg.in/mgo.v2/bson"
  // Other packages are used as well
)

type MyData struct {
  Something int
  Collection []interface{}
}

func main() {
    // I'm using SimpleJson for parsing JSON
    collection, cerr := jsonFromExternalApi.Get("collection").Array()
    if cerr != nil {
      logger.Debug.Fatalln(cerr)
    }

    // Save response to Mongo (leaving out all the connection code)
    c := mongoSess.DB("mydb").C("mycollection")
    insertErr := c.Insert(&Producer{npn, licenses })
}

The issue was that SimpleJSON was returning the array of objects from my API call as a []interface{}. I was not aware I could simply declare part of a struct to be an interface so instead of just correcting what Go's compiler was telling me was wrong I was making it way harder than it should have been.

Coming from loosely typed scripting languages, stuff like this really trips me up and sometimes its hard to see the benefit but hopefully this helps someone out one day.

Upvotes: 1

Views: 8549

Answers (2)

Akash Shinde
Akash Shinde

Reputation: 955

Here you are not defining proper type to Collection in your MyData struct.

Collection []string    //This is what you are defining.

But from Json you are not getting string array,you are getting map[string]interface{}

This is the reason you are not filling Mydata struct properly

Correct MyData struct will be

type MyData struct {
 Something string   
 Collection map[string]string // This actually contains more than strings but I'll be happy if I can just get strings saved 
}

Upvotes: 1

Pravin Mishra
Pravin Mishra

Reputation: 8434

Looks you have the wrong data structure.

insertErr := c.Insert(&MyData{something, collection})

something => string and collection => slice

You code should be like this:

insertErr := c.Insert(&MyData{"something", []string{"obj1", "value"}})

Here is the working code.

[{Something:something Collection:[obj1 value]} {Something:something Collection:[obj1 value]} {Something:something Collection:[obj1 value]} {Something:something Collection:[obj1 value]}]

For further reference, mgo has great documentation and you can find sample code and details about running mongodb queries here.

Upvotes: 4

Related Questions