2015-01-01 5 views
2

У меня есть набор документов, которые были вставлены в Монго ищет что-то вроде этого:запрос документы с различными структурами для результатов

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) 

я вся «Статистика» внедренная структурой в результатах - как я могу отфильтровать только одно поле из поддокумента в и поместить его в результирующий набор?

Спасибо!

ответ

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

... что именно то, что я хотел бы ожидать ,

0

Возможно, это поможет другим людям - по существу, я пытался взять документ со встроенным документом и возвращать результирующий набор, как я бы сделал в SQL с выбором a.LastName + ',' + a.FirstName как имя, b.OtherData и по существу имеют другой «стол»/«документ».

Итак, вот мое текущее решение - любите получать лучшие (более совершенные?)!

Я создал новую структуру и я использую '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" 
      } 
} 
Смежные вопросы