|
How can I decode lookup(aggregation) result to nested structure?
This is my test code and I expected all inner structures are decoded.
package main
|
|
import (
|
"context"
|
"fmt"
|
"github.com/mongodb/mongo-go-driver/bson"
|
"github.com/mongodb/mongo-go-driver/mongo"
|
"github.com/mongodb/mongo-go-driver/bson/primitive"
|
"github.com/mongodb/mongo-go-driver/mongo/options"
|
)
|
|
func main() {
|
type item struct {
|
ID primitive.ObjectID `bson:"_id"`
|
Name string
|
Price int
|
}
|
|
type order struct {
|
ID primitive.ObjectID `bson:"_id"`
|
Name string
|
Item []primitive.ObjectID
|
Qty int
|
}
|
|
type user struct{
|
ID primitive.ObjectID `bson:"_id"`
|
Name string
|
Orders []primitive.ObjectID
|
}
|
|
type fOrder struct {
|
ID primitive.ObjectID `bson:"_id"`
|
Name string
|
Item []item
|
Qty int
|
}
|
|
type fUser struct {
|
ID primitive.ObjectID `bson:"_id"`
|
Name string
|
Orders []fOrder
|
}
|
|
ctx := context.Background()
|
|
|
client, err := mongo.NewClient("mongodb://localhost:27027")
|
if err != nil {
|
panic(err)
|
}
|
|
err = client.Connect(ctx)
|
if err != nil {
|
panic(err)
|
}
|
|
db := client.Database("testDb")
|
err = db.Drop(ctx)
|
if err != nil {
|
panic(err)
|
}
|
|
items := client.Database("testDb").Collection("items")
|
orders := client.Database("testDb").Collection("orders")
|
users := client.Database("testDb").Collection("users")
|
|
item1 := item{ID:primitive.NewObjectID(), Name: "a", Price: 12}
|
item2 := item{ID:primitive.NewObjectID(), Name: "b", Price: 20}
|
item3 := item{ID:primitive.NewObjectID(), Name: "c", Price: 5}
|
item4 := item{ID:primitive.NewObjectID(), Name: "d", Price: 4}
|
item5 := item{ID:primitive.NewObjectID(), Name: "e", Price: 50}
|
|
|
order1 := order{ID: primitive.NewObjectID(), Name: "o1", Item: []primitive.ObjectID{item1.ID, item2.ID}, Qty: 1}
|
order2 := order{ID: primitive.NewObjectID(), Name: "o2", Item: []primitive.ObjectID{item2.ID, item3.ID, item4.ID}, Qty: 3}
|
|
order3 := order{ID: primitive.NewObjectID(), Name: "o3", Item: []primitive.ObjectID{item5.ID, item3.ID}, Qty: 2}
|
order4 := order{ID: primitive.NewObjectID(), Name: "o4", Item: []primitive.ObjectID{item5.ID}, Qty: 1}
|
order5 := order{ID: primitive.NewObjectID(), Name: "o5", Item: []primitive.ObjectID{item1.ID, item2.ID, item3.ID, item4.ID}, Qty: 5}
|
|
user1 := user{ID:primitive.NewObjectID(), Name: "John", Orders:[]primitive.ObjectID{order1.ID, order2.ID}}
|
user2 := user{ID:primitive.NewObjectID(), Name: "Brown", Orders:[]primitive.ObjectID{order3.ID, order4.ID, order5.ID}}
|
|
|
err = client.UseSession(ctx, func(sessionContext mongo.SessionContext) error {
|
if err != nil {
|
return err
|
}
|
|
_, err = items.InsertMany(sessionContext, []interface{}{item1, item2, item3, item4, item5})
|
if err != nil {
|
return err
|
}
|
|
_, err = orders.InsertMany(sessionContext, []interface{}{order1, order2, order3, order4, order5})
|
if err != nil {
|
return err
|
}
|
|
_, err = users.DeleteOne(sessionContext, bson.D{{"_id", "a"}})
|
if err != nil {
|
return err
|
}
|
|
_, err = users.InsertMany(sessionContext, []interface{}{user1, user2})
|
if err != nil {
|
return err
|
}
|
|
return nil
|
})
|
if err != nil {
|
panic(err)
|
}
|
|
cur, err := users.Aggregate(nil, mongo.Pipeline{
|
{{"$lookup", bson.D{{"from", "orders"}, {"localField","orders"}, {"foreignField", "_id"}, {"as", "orders"}}}},
|
{{"$unwind", "$orders"}},
|
{{"$lookup", bson.D{{"from", "items"}, {"localField","orders.item"}, {"foreignField", "_id"}, {"as", "item"}}}},
|
{{"$group", bson.D{{"_id", "$_id"}, {"name", bson.D{{"$first","$name"}}}, {"orders", bson.D{{"$push", "$orders"}}}}},
|
}}, options.Aggregate())
|
if err != nil{
|
panic(err)
|
}
|
|
for cur.Next(nil) {
|
u := new(fUser)
|
cur.Decode(u)
|
fmt.Println(u)
|
}
|
|
}
|
But the result is:
&{ObjectID("5c0f4181ae3cac264bc9e1ec") Brown []}
|
&{ObjectID("5c0f4181ae3cac264bc9e1eb") John []}
|
|