Я думаю, что это один из самых популярных вопросов на теге mongo
. И я должен сказать, если вам нужно, чтобы вы делали что-то не так, и, возможно, вам следует использовать СУРБД вместо Монго, так как падение производительности в подобных запросах приведет к аннулированию всей прибыли от функций Mongo, таких как схемы, документы «все-в-одном» и т. Д. ..
В любом случае, ответ прост - вы не можете получить список фильмов, как хотите. Mongo's find
может возвращать только полный или частичный документ верхнего уровня. Я имею в виду лучший результат вы можете получить с помощью db.collection.find({}, {'films': 1})
запроса является список как
{
films: [
{
title: "The Shawshank Redemption",
year: 1994
},
{
title: "The Godfather",
year: 1972
}
]
},
{
films: [
{
title: "12 Angry Men",
year: 1957
},
{
title: "The Dark Knight",
year: 2008
}
]
}
Не то, что вы expectied, верно?
Единственный способ получить массив как
{
title: "The Shawshank Redemption",
year: 1994
},
{
title: "The Godfather",
year: 1972
},
{
title: "12 Angry Men",
year: 1957
},
{
title: "The Dark Knight",
year: 2008
}
является использование aggregation.
Основной запрос Монго, чтобы получить массив фильмов
db.collection.aggregate([{
$unwind: '$films'
}, {
$project: {
title: '$films.title',
year: '$films.year'
}
}])
код Go для этого запроса
package main
import (
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
"fmt"
)
func main() {
session, err := mgo.Dial("mongodb://127.0.0.1:27017/db")
if err != nil {
panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
c := session.DB("db").C("collection")
pipe := c.Pipe(
[]bson.M{
bson.M{
"$unwind": "$films",
},
bson.M{
"$project": bson.M{
"title": "$films.title",
"year": "$films.year",
},
},
},
)
result := []bson.M{}
err = pipe.All(&result)
fmt.Printf("%+v", result) // [map[_id:ObjectIdHex("57a2ed6640ce01187e1c9164") title:The Shawshank Redemption year:1994] map[_id:ObjectIdHex("57a2ed6640ce01187e1c9164") title:The Godfather year:1972] map[_id:ObjectIdHex("57a2ed6f40ce01187e1c9165") title:12 Angry Men year:1957] map[year:2008 _id:ObjectIdHex("57a2ed6f40ce01187e1c9165") title:The Dark Knight]]
}
Если вам нужны дополнительные условия для выбора документов верхнего уровня кода будет
pipe := c.Pipe(
[]bson.M{
bson.M{
"$match": bson.M{
"name": "Jane",
},
},
bson.M{
"$unwind": "$films",
},
bson.M{
"$project": bson.M{
"title": "$films.title",
"year": "$films.year",
},
},
},
)
// result [map[_id:ObjectIdHex("57a2ed6640ce01187e1c9164") title:The Shawshank Redemption year:1994] map[title:The Godfather year:1972 _id:ObjectIdHex("57a2ed6640ce01187e1c9164")]]
Для фильтров необходимо использовать следующий запрос
pipe := c.Pipe(
[]bson.M{
bson.M{
"$unwind": "$films",
},
bson.M{
"$project": bson.M{
"title": "$films.title",
"year": "$films.year",
},
},
bson.M{
"$match": bson.M{
"year": bson.M{
"$gt": 2000,
},
},
},
},
)
// result [map[_id:ObjectIdHex("57a2ed6f40ce01187e1c9165") year:2008 title:The Dark Knight]]
Проблема с агрегацией - это простой факт, что большая часть операций агрегации не использует индексы и может быть медленной в больших коллекциях. Вот почему я предложил вам подумать о РСУБД, которая может быть лучшим выбором, если вам нужно много скоплений.
И нет никакого способа, чтобы получить []string
от mgo
, как она всегда возвращает bson.M
(или []bson.M
), который является map[string]interface{}
.
Большое спасибо за подробный ответ. Возможно, вы правы, и мне будет лучше с Postgres. –
@curious_gudleif умный выбор. –