查询具有不同结构的文档以获得结果

Query Document with different struct for results

我有一组文档被插入到 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)
    ...
}

这行得通 - 我的问题是,如何只包含 'Stats' 结构中的一个字段?换句话说, 我基本上希望 "projection" 是这样的:

projection := bson.M{"lastName":1, ..., "stats.userStatus":1}  <-- stats.userStatus doesn't work
...
err := x.Find({query user collection}).Select(projection).All(&result)

我在结果中得到了整个 "Stats" 嵌入结构 - 我怎样才能从子文档中过滤掉一个字段并将其放入结果集中?

谢谢!

它非常适合我,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}]}]

...这正是我所期望的。

也许这会对其他人有所帮助 - 本质上我是在尝试获取带有嵌入式文档的文档和 return 结果集,就像我在 SQL 中使用 select a.LastName + ', ' + a.FirstName as Name, b.OtherData 和本质上有不同的 'table' / 'document'。

所以这是我当前的解决方案 - 喜欢获得更好的解决方案(性能更高?)!

我创建了一个新结构并且我正在使用 'mapstructure' 库

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