首页 > 解决方案 > 如何执行仅获取第一个元素的查找

问题描述

我有这两个结构:

Category struct {
    ID           primitive.ObjectID `bson:"_id"`
    Name         string             `bson:"name"`
}

Book struct {
    ID           primitive.ObjectID `bson:"_id"`
    Name         string             `bson:"name"`
    Category     *Category          `bson:"category"`
}

我想找到一本汇总其类别的书并执行此查询

// lookup stage
lookupStage := bson.D{{"$lookup", bson.D{
    {"from", "category"},
    {"localField", "category"},
    {"foreignField", "_id"},
    {"as", "category"}}}}

通过此查找,我会将获取的类别文档放入图书的类别字段中。

// match stage (cut for simplicity, it doesn't care)
var matchStage bson.D = ...

pipeline := mongo.Pipeline{
    matchStage,
    lookupStage,
}

cur, err := bookCollection.Aggregate(context.TODO(), pipeline)

cur.Decode(&book)

如果我直接在 MongoDB 中执行查询一切正常,但在 Go 中我得到一个空类别。我认为问题在于查找返回一个数组但我试图将它映射到一个对象上。

所以问题是:如何获取查找操作产生的数组的第一个元素并将其放置在 book 实例中?

我正在使用 mongo 官方驱动程序。

标签: mongodbgo

解决方案


如果我直接在 MongoDB 中执行查询一切正常,但在 Go 中我得到一个空类别。我认为问题在于查找返回一个数组但我试图将它映射到一个对象上。

$lookup阶段确实返回一个数组,但如果这是您的问题,您可能会收到一个错误,例如cannot decode array into a Category. 它可能是由其他原因引起的,下面的答案将显示一个工作示例,希望也能帮助您解决问题。

这里有两种选择,具体取决于您的用例。首先是声明Category为数组,即

type Book struct {
    ID       primitive.ObjectID `bson:"_id"`
    Name     string             `bson:"name"`
    Category []*Category        `bson:"category"`
}

其次,您可以利用$unwind阶段来删除阵列。例如:

collection := client.Database("go").Collection("book")
lookupStage := bson.D{{"$lookup", bson.D{
    {"from", "category"},
    {"localField", "category"},
    {"foreignField", "_id"},
    {"as", "category"}}}}

unwindStage := bson.D{{"$unwind", "$category"}}
pipeline := mongo.Pipeline{lookupStage, unwindStage}

cursor, err := collection.Aggregate(context.TODO(), pipeline)
defer cursor.Close(context.TODO())
if err != nil {
    panic(err)
}
cursor.Next(context.TODO())
var book Book
err = cursor.Decode(&book)
if err != nil {
    panic(err)
}
fmt.Println(book)

说了以上所有内容,根据您的用例,您应该重新考虑架构。假设图书类别不会经常更改,您可以将其嵌入CategoryBook. 这将简化很多查询,因为图书类别可能是图书的重要信息。

有关模式设计的更多信息,请参阅使用模式构建:摘要


推荐阅读