使用mgo与转换为map[string]interface{}的嵌套文档。如何遍历map?

huangapple go评论74阅读模式
英文:

Using mgo with nested documents that convert to map[string]interface{}. How to iterate through maps?

问题

我在MongoDB数据库中有以下文档,但有时我不知道某些文档的结构:

{
"_id" : ObjectId("54e58ea6128ae6385faa576e"),
"date" : ISODate("2015-02-19T00:00:00.000Z"),
"lat" : "53.5558774",
"lng" : "-113.4939486",
"apparentTemp" : -1.727777777777777,
"timezone" : "America/Edmonton",
"humidity" : 0.92,
"city" : "Edmonton",
"dewPoint" : 26.85,
"temp" : -1.727777777777777,
"summary" : "Light Snow",
"gmt_offset" : -7,
"windSpeed" : 0.13,
"windBearing" : 87,
"precipIntensity" : 0.0086,
"precipProbability" : 0.44,
"forecast" : [
{
"humidity" : 0.86,
"windSpeed" : 0.86,
"precipProbability" : 0.83,
"dewPoint" : 28.26,
"temp" : -0.02777777777777817,
"date" : ISODate("2015-02-19T00:00:00.000Z"),
"windBearing" : 63,
"precipIntensity" : 0.0528,
"apparentTemp" : -0.02777777777777817,
"summary" : "Snow (Under 1 in.)"
}
]
}

我使用以下代码查询数据库,并尝试从forecast子文档中构建一个仅包含"date"和"temp"的数组,到目前为止,我已经使用了以下代码,但无法查询到键以获取值的点:

var results bson.M
err2 := collection.Find(bson.M{
"city": vars["city"],
"forecast.1": bson.M{"$exists": true},
}).Sort("-date").One(&results)
if err2 != nil {
log.Fatal(err2)
}

switch reflect.TypeOf(results["forecast"]).Kind() {
case reflect.Slice:
s := reflect.ValueOf(results["forecast"])

for i := 0; i < s.Len(); i++ {
    hourly_temps := s.Index(i).Interface()
    fmt.Fprintln(w, hourly_temps)
}

}

我得到的输出是:

map[humidity:0.86 temp:-.0277777777777817 windBearing:63 windSpeed:0.86 precipProbability:0.83 dewPoint:28.26 date:2015-02-19 00:00:00 -0700 MST precipIntensity:0.0528 apparentTemp:-0.02777777777777817 summary:Snow (Under 1 in.)]

我对Go语言还不太熟悉,不确定如何提取date和temp的值。非常感谢您的帮助。

英文:

I have the following documents in a MongoDB database, but sometimes I don't know the structure for certain:

{
    &quot;_id&quot; : ObjectId(&quot;54e58ea6128ae6385faa576e&quot;),
    &quot;date&quot; : ISODate(&quot;2015-02-19T00:00:00.000Z&quot;),
    &quot;lat&quot; : &quot;53.5558774&quot;,
    &quot;lng&quot; : &quot;-113.4939486&quot;,
    &quot;apparentTemp&quot; : -1.727777777777777,
    &quot;timezone&quot; : &quot;America/Edmonton&quot;,
    &quot;humidity&quot; : 0.92,
    &quot;city&quot; : &quot;Edmonton&quot;,
    &quot;dewPoint&quot; : 26.85,
    &quot;temp&quot; : -1.727777777777777,
    &quot;summary&quot; : &quot;Light Snow&quot;,
    &quot;gmt_offset&quot; : -7,
    &quot;windSpeed&quot; : 0.13,
    &quot;windBearing&quot; : 87,
    &quot;precipIntensity&quot; : 0.0086,
    &quot;precipProbability&quot; : 0.44,
    &quot;forecast&quot; : [ 
        {
            &quot;humidity&quot; : 0.86,
            &quot;windSpeed&quot; : 0.86,
            &quot;precipProbability&quot; : 0.83,
            &quot;dewPoint&quot; : 28.26,
            &quot;temp&quot; : -0.02777777777777817,
            &quot;date&quot; : ISODate(&quot;2015-02-19T00:00:00.000Z&quot;),
            &quot;windBearing&quot; : 63,
            &quot;precipIntensity&quot; : 0.0528,
            &quot;apparentTemp&quot; : -0.02777777777777817,
            &quot;summary&quot; : &quot;Snow (Under 1 in.)&quot;
        }
    ]
}

I have used the following code to query the database and am attempting to build an array of just the "date" and "temp" from forecast sub-document and have so far used the following code, but can't get to the point where I can query on the key to get the value:

var results bson.M
err2 := collection.Find(bson.M{
	&quot;city&quot;: vars[&quot;city&quot;],
	&quot;forecast.1&quot;: bson.M{&quot;$exists&quot;: true},
}).Sort(&quot;-date&quot;).One(&amp;results)
if err2 != nil {
	log.Fatal(err2)
}

switch reflect.TypeOf(results[&quot;forecast&quot;]).Kind() {
case reflect.Slice:
	s := reflect.ValueOf(results[&quot;forecast&quot;])

	for i := 0; i &lt; s.Len(); i++ {
		hourly_temps := s.Index(i).Interface()
		fmt.Fprintln(w, hourly_temps)
	}
}

The output I'm getting is:

map[humidity:0.86 temp:-.0277777777777817 windBearing:63 windSpeed:0.86        precipProbability:0.83 dewPoint:28.26 date:2015-02-19 00:00:00 -0700 MST precipIntensity:0.0528 apparentTemp:-0.02777777777777817 summary:Snow (Under 1 in.)]

I am fairly new to go and unsure of how to extract the value from date and temp. Any help would be greatly appreciated.

答案1

得分: 0

经过大量的研究和论坛搜索,我找到了上述问题的答案。

由于我对我的结构有一些基本信息,我知道有一个时间戳,并且将有一个与预测键相关的子文档:

package main

import (
    "fmt"
    "github.com/gorilla/mux"
    "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
    "log"
    "net/http"
    "time"
)

var (
    mgoSession *mgo.Session
)

func ConnectDb() {
    if mgoSession == nil {
        session, err := mgo.Dial("localhost")
        if err != nil {
            log.Print(err)
        }
        session.SetMode(mgo.Monotonic, true)
        mgoSession = session
    }
    return
}

func CloseDb() {
    mgoSession.Close()
    return
}

type WeatherForecastData struct {
    Timestamp time.Time                `json:"timestamp,omitempty" bson:"date,omitempty"`
    Forecast  []map[string]interface{} `json:"forecast" bson:"forecast"`
}

type WeatherFutureForecast struct {
    Timestamp   time.Time `json:"timestamp,omitempty" bson:"date,omitempty"`
    Temperature float64   `json:"temperature"`
}

func GetWeatherForecast(city string) []WeatherFutureForecast {
    session := mgoSession.Clone()
    defer session.Close()

    collection := mgoSession.DB("db").C("weather_forecast_io")

    var results WeatherForecastData
    var forecastResults []WeatherFutureForecast

    err := collection.Find(bson.M{
        "city":       city,
        "forecast.1": bson.M{"$exists": true},
    }).Sort("-date").One(&results)
    if err != nil {
        log.Print(err)
    } else {
        for _, value := range results.Forecast {
            if _, ok := value["date"]; ok {
                if _, ok2 := value["temp"]; ok2 {
                    date := value["date"].(time.Time)
                    temp := value["temp"].(float64)
                    day := WeatherFutureForecast{Timestamp: date, Temperature: temp}
                    forecastResults = append(forecastResults, day)
                }
            }
        }
    }
    return forecastResults
}

func main() {
    ConnectDb()
    defer CloseDb()
    router := mux.NewRouter().StrictSlash(true)
    router.HandleFunc("/weather/forecast/{city}", WeatherForecast)
    log.Fatal(http.ListenAndServe(":8080", router))
}

基本上,我使用了map[string]interface{}来解决我未知的预测子文档结构的问题。然后,我可以循环遍历并提取必要的信息。

英文:

After much research and forum searching I found an answer to the aforementioned problem.

Since I knew some basic information about my structure, I knew there was a timestamp and that there was going to a sub-document related to the forecast key:

package main
import (
&quot;fmt&quot;
&quot;github.com/gorilla/mux&quot;
&quot;gopkg.in/mgo.v2&quot;
&quot;gopkg.in/mgo.v2/bson&quot;
&quot;log&quot;
&quot;net/http&quot;
&quot;time&quot;
)
var (
mgoSession *mgo.Session
)
func ConnectDb() {
if mgoSession == nil {
session, err := mgo.Dial(&quot;localhost&quot;)
if err != nil {
log.Print(err)
}
session.SetMode(mgo.Monotonic, true)
mgoSession = session
}
return
}
func CloseDb() {
mgoSession.Close()
return
}
type WeatherForecastData struct {
Timestamp time.Time                `json:&quot;timestamp,omitempty&quot; bson:&quot;date,omitempty&quot;`
Forecast  []map[string]interface{} `json:&quot;forecast&quot; bson:&quot;forecast&quot;`
}
type WeatherFutureForecast struct {
Timestamp   time.Time `json:&quot;timestamp,omitempty&quot; bson:&quot;date,omitempty&quot;`
Temperature float64   `json:&quot;temperature&quot;`
}
func GetWeatherForecast(city string) []WeatherFutureForecast {
session := mgoSession.Clone()
defer session.Close()
collection := mgoSession.DB(&quot;db&quot;).C(&quot;weather_forecast_io&quot;)
var results WeatherForecastData
var forecastResults []WeatherFutureForecast
err := collection.Find(bson.M{
&quot;city&quot;:       city,
&quot;forecast.1&quot;: bson.M{&quot;$exists&quot;: true},
}).Sort(&quot;-date&quot;).One(&amp;results)
if err != nil {
log.Print(err)
} else {
for _, value := range results.Forecast {
if _, ok := value[&quot;date&quot;]; ok {
if _, ok2 := value[&quot;temp&quot;]; ok2 {
date := value[&quot;date&quot;].(time.Time)
temp := value[&quot;temp&quot;].(float64)
day := WeatherFutureForecast{Timestamp: date, Temperature: temp}
forecastResults = append(forecastResults, day)
}
}
}
}
return forecastResults
}
func main() {
ConnectDb()
defer CloseDb()
router := mux.NewRouter().StrictSlash(true)
router.HandleFunc(&quot;/weather/forecast/{city}&quot;, WeatherForecast)
log.Fatal(http.ListenAndServe(&quot;:8080&quot;, router))
}

Basically I used map[string]interface to solve the problem of my unknown forecast sub-document structure. From that I was then able to loop through and extract the necessary information.

huangapple
  • 本文由 发表于 2015年2月28日 07:11:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/28775929.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定