英文:
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:
{
"_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.)"
}
]
}
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{
"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)
}
}
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 (
"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))
}
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论