我有一组插入Mongo的文档,看起来像这样:
type Stats struct {
UserStatus string `json:"userStatus" bson:"userStatus"`
... a bunch more fields
}
type User struct {
ID bson.ObjectId `json:"-" bson:"_id"`
LastName string `json:"lastName" bson:"lastName"`
FirstName string `json:"firstName" bson:"firstName"`
Role string `json:"role" bson:"role"`
Tags []string `json:"tags" bson:"tags"`
... (a bunch more fields)
Stats UserStats `json:"stats" bson:"stats"`
}
我想查询它以获取特定报告,所以我尝试了这个:
func UserNameReport() {
... get mongo session, etc.
// create struct of just the data I want returned
type UserNames struct {
LastName string `json:"lastName" bson:"lastName"`
FirstName string `json:"firstName" bson:"firstName"`
... etc
UserStats Stats `json:"stats" bson:"stats"`
}
projection := bson.M{"lastName":1, "firstName":1, etc}
result := []UserNames{}
err := x.Find({query user collection}).Select(projection).All(&result)
...
}
这是有效的 - 我的问题是,我怎样才能只包含“统计数据”中的一个字段。结构?换一种说法, 我基本上想要"投影"是这样的:
projection := bson.M{"lastName":1, ..., "stats.userStatus":1} <-- stats.userStatus doesn't work
...
err := x.Find({query user collection}).Select(projection).All(&result)
我得到了整个&#34;统计数据&#34;结果中的嵌入式结构 - 如何从子文档中过滤掉一个字段并将其放入结果集中?
谢谢!
答案 0 :(得分:1)
使用MongoDB 2.6.5
对我来说非常适合以下代码:
package main
import (
"fmt"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"log"
)
type Statistics struct {
Url string
Hits int
}
type Person struct {
Num int
Uuid string
Name string
Stats []Statistics
}
func main() {
// Connect to the database
session, err := mgo.Dial("localhost")
if err != nil {
panic(err)
}
defer session.Close()
// Remove people collection if any
c := session.DB("test").C("people")
c.DropCollection()
// Add some data
err = c.Insert(
&Person{1, "UUID1", "Joe", []Statistics{Statistics{"a", 1}, Statistics{"b", 2}}},
&Person{2, "UUID2", "Jane", []Statistics{Statistics{"c", 3}, Statistics{"d", 4}}},
&Person{3, "UUID3", "Didier", []Statistics{Statistics{"e", 5}, Statistics{"f", 6}}})
if err != nil {
log.Fatal(err)
}
result := []Person{}
err = c.Find(bson.M{"$or": []bson.M{bson.M{"uuid": "UUID3"}, bson.M{"name": "Joe"}}}).Select(bson.M{"num": 1, "name": 1, "stats.hits": 1}).All(&result)
if err != nil {
log.Fatal(err)
}
fmt.Println(result)
}
结果:
[{1 Joe [{ 1} { 2}]} {3 Didier [{ 5} { 6}]}]
......这正是我所期待的。
答案 1 :(得分:0)
也许这会对其他人有所帮助 - 实际上我试图用一个嵌入式文档来获取一个文档并返回一个结果集,就像我在SQL中一样,选择a.LastName +&#39;,&#39; + a.FirstName作为名称,b。其他数据,实质上有一个不同的表&#39; /&#39;文件&#39;。
所以这是我目前的解决方案 - 喜欢获得更好的(更高效的?)!
我创建了一个新的结构,我使用了#map;地图结构&#39;图书馆
import "github.com/goinggo/mapstructure"
type Stats struct {
UserStatus string `json:"userStatus" bson:"userStatus"`
... a bunch more fields
}
type User struct {
ID bson.ObjectId `json:"-" bson:"_id"`
LastName string `json:"lastName" bson:"lastName"`
FirstName string `json:"firstName" bson:"firstName"`
Role string `json:"role" bson:"role"`
Tags []string `json:"tags" bson:"tags"`
... (a bunch more fields)
Stats UserStats `json:"stats" bson:"stats"`
}
type MyReportItem struct {
FirstName string `json:"firstName" jpath:"firstName"`
LastName string `json:"lastName" jpath:"lastName"`
Status string `json:"status" jpath:"stats.userStatus"`
}
type MyReport struct {
Results []MyReportItem `json:"results"`
}
func xxxx(w http.ResponseWriter, r *http.Request) {
var users MyReportItem
// the results will come back as a slice of map[string]interface{}
mgoResult := []map[string]interface{}{}
// execute the query
err := c.Find(finder).Select(projection).All(&mgoResult)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
user := MyReportItem{}
// iterate through the results and decode them into the MyReport struct
for _, x := range mgoResult {
docScript, _ := json.Marshal(x)
docMap := map[string]interface{}{}
json.Unmarshal(docScript, &docMap)
err := mapstructure.DecodePath(docMap, &user)
if err == nil {
users.Results = append(users.Results, user)
}
}
... send back the results ...
_ := json.NewEncoder(w).Encode(&users)
}
现在我在表单中得到了一些对象:
results: [
{
firstName: "John",
lastName: "Doe",
status: "active"
}
...
]
而不是:
{
firstName: "John",
lastName: "Doe",
stats: {
status: "active"
}
}