неструктурированный внутренний документ с mgo

У меня есть документ, который имеет следующую структуру

{ "_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 } }

САМОЕ ВАЖНОЕ заключается в том, что структура поддокумента под ключом «значение» является переменной, поэтому я не могу создать для этого структуру. Я попытался последовать предложению здесь - Неструктурированные коллекции MongoDB с mgo

И я пришел с этим кодом ---

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
      }
    }

}

Когда я пытаюсь собрать это с помощью анализатора go build -v -o, он показывает мне эту ошибку ---

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

Я ужасно застрял с этим. Ничего не получается. Пожалуйста, может кто-нибудь помочь?

Спасибо


Я придумал этот код после некоторых исследований. Не самый оптимизированный точно. Но для моего случая работает. Принял помощь от 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
      }
    }

}

Дайте мне знать ваши мысли по этому поводу.

Спасибо


person SRC    schedule 08.07.2014    source источник
comment
Тип bson.M сопоставляет строки с interface{}, поэтому вам нужно ввести утверждать это, чтобы использовать его. Вы пробовали m.Value["value"].(map[string]interface{})["total_visit"]?   -  person Ainar-G    schedule 08.07.2014
comment
Да, это то, что я изначально придумал, но затем в сочетании с ответом ниже я изменил это. Спасибо, в любом случае.   -  person SRC    schedule 08.07.2014


Ответы (1)


При тестировании чего-то нового всегда используйте много fmt.Printf, чтобы почувствовать это, как говорится.

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

Должно быть

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

А также

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

Должно быть:

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

Ваш m.Value является «значением», поэтому вы можете использовать m.Value["total_visit"] напрямую.

детская площадка

//редактировать

Вы можете использовать inline только для захвата любых полей, которые не являются частью исходной структуры, но, поскольку ваша структура имеет только 2 поля (Id and Value), вам это не нужно.

Теперь, если бы вы сохранили ,inline, вы бы использовали его так:

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

Поскольку m.Value["value"] – это interface{}, вам нужно ввести assert, чтобы вернуть исходное значение, bson.M перед тем, как вы мог использовать его.

person OneOfOne    schedule 08.07.2014
comment
К сожалению, этот код дает мне этот вывод (Ваш второй println) ‹nil›. Это для каждого ключа, который я пробовал. Выкладываю одну работу. Пожалуйста, дайте мне знать, что вы думаете об этом - person SRC; 08.07.2014
comment
Я лично проверил это, создал коллекцию и сохранил выложенный вами документ json, и это сработало, какую версию go/mgo вы использовали? - person OneOfOne; 08.07.2014
comment
Не видел твоего редактирования, когда комментировал. Извиняюсь. Да, я сделал что-то похожее на то, что вы мне сказали, но ваше точнее. - person SRC; 08.07.2014
comment
прохладно. Спасибо. также решил некоторую путаницу. Большое спасибо. принимая этот ответ - person SRC; 08.07.2014