3

I have a document which has this following structure

{ "_id" : "736722976", "value" : { "total_visit" : 4, "FIFA World Cup 2014" : 1, "Germany" : 1, "Algeria" : 1, "Thomas Muller" : 1, "Mesut Ozil" : 1, "Monsoon" : 1, "India Meteorological Department (IMD)" : 1, "Web Exclusive" : 2, "Specials" : 1, "Tapas Pal" : 1, "Twitter Trends" : 1, "Sunanda Pushkar" : 1, "Shashi Tharoor" : 1, "AIIMS" : 1, "special" : 1 } }

THE MOST IMPORTANT thing is that the sub document structure under the key "value" is variable so I can not create a structure for that. I tried to follow the suggestion here - Unstructured MongoDB collections with mgo

And I came with this code ---

package main

import ("fmt"
"labix.org/v2/mgo"  //importing mgo
"labix.org/v2/mgo/bson"
_ "reflect"
)

type AnalysisStruct struct{
  Id string `bson:"_id,omitempty"`
  Value bson.M `bson:",inline"`
}

func main() {
    var m AnalysisStruct
    //connecting to localhost mongodb
    session, err := mgo.Dial("localhost")
    if err != nil {  
        panic(err)
    }
    defer session.Close()
    c := session.DB("my_analysis_db").C("analysis_mid_2")
    iter := c.Find(nil).Iter()
    for{
      if iter.Next(&m){
          fmt.Println(m.Value["value"]["total_visit"])
      }else{
          break
      }
    }

}

When I try to build this using go build -v -o analyzer it shows me this error---

./analyzer.go:32: invalid operation: m.Value["value"]["total_visit"] (index of type interface {})

I am terribly stuck with this. Can not get anything going. Please can somebody help?

Thanks


I cam up with this code after doing some research. Not the most optimized one for sure. But for my case it works. Took help from http://blog.denevell.org/golang-interface-type-assertions-switch.html

https://groups.google.com/forum/#!topic/mgo-users/JYE-CP15az4

package main

import ("fmt"
"labix.org/v2/mgo"  //importing mgo
"labix.org/v2/mgo/bson"
_ "reflect"
)

type AnalysisStruct struct{
  Id string `bson:"_id,omitempty"`
  Value bson.M `bson:",inline"`
}

func main() {
    var m AnalysisStruct
    //connecting to localhost mongodb
    session, err := mgo.Dial("localhost")
    if err != nil {  
        panic(err)
    }
    defer session.Close()
    c := session.DB("consumergenepool_db").C("analysis_mid_2")
    iter := c.Find(nil).Iter()
    for{
      if iter.Next(&m){
           s := m.Value["value"].(bson.M)
           data, _ := bson.Marshal(s)
           var m bson.M
           _ = bson.Unmarshal(data, &m)
           fmt.Println(m)
           for k, v := range m{
              fmt.Print(k)
              fmt.Print(" :: ")
              fmt.Println(v)
           }
      }else{
          break
      }
    }

}

Let me know your thoughts on this.

Thanks

Community
  • 1
  • 1
SRC
  • 2,123
  • 3
  • 31
  • 44
  • [bson.M](http://godoc.org/labix.org/v2/mgo/bson#M) type maps strings to `interface{}`, so you need to type assert it in order to use it. Have you tried `m.Value["value"].(map[string]interface{})["total_visit"]`? – Ainar-G Jul 08 '14 at 13:37
  • Yes that is what I originally came up with but then combined with the answer bellow I changed that. Thanks anyway. – SRC Jul 08 '14 at 13:50

1 Answers1

1

When testing something new always use a lot of fmt.Printf's to get a feel for it, that being said.

Value bson.M `bson:",inline"`

Should be

Value bson.M `bson:"value,omitempty"`

And

fmt.Println(m.Value["value"]["total_visit"])

Should be:

fmt.Printf("%#v\n", m)
fmt.Println(m.Value["total_visit"])

Your m.Value is "value", so you can use m.Value["total_visit"] directly.

playground

//edit

You can only use inline to catch any fields that that aren't a part of the original struct, but since your struct only has 2 fields (Id and Value), you don't need it.

Now if you were to keep ,inline you would use it like this:

    if v, ok := m.Value["value"].(bson.M); ok {
        fmt.Println(v["total_visit"])
    }

Because m.Value["value"] is an interface{}, you have to type assert it back to it's original value, bson.M before you could use it.

OneOfOne
  • 95,033
  • 20
  • 184
  • 185
  • Unfortunately this code gives me this output (Your second println) . That is for every key i tried. I am posting one work around. Please let me know what you think of this – SRC Jul 08 '14 at 13:40
  • I personally tested it, created a collection and saved the json document you posted and it worked, what version of go / mgo did you use? – OneOfOne Jul 08 '14 at 13:44
  • Did not see your edit when I was commenting. Sorry. Yes, I did something similar of what you told me but yours is more precise. – SRC Jul 08 '14 at 13:45
  • 1
    cool. Thanks. did solve some confusion as well. Thanks a lot. accepting this answer – SRC Jul 08 '14 at 13:49