douqianke7467 2015-09-18 12:35
浏览 68
已采纳

Mgo如何在嵌套数组中查找嵌套文档?

Here below I have document structure designed as follows:

type MIS_Course struct {
    ID   bson.ObjectId `bson:"_id,omitempty"`
    Name string        `bson:"crse_name"`
}

type MIS_Department struct {
    ID      bson.ObjectId `bson:"_id,omitempty"`
    Name    string        `bson:"dept_name"`
    Courses []MIS_Course  `bson:"crse_list"`
}

type MIS_School struct {
    ID          bson.ObjectId    `bson:"_id,omitempty"`
    Name        string           `bson:"school_name"`
    Departments []MIS_Department `bson:"dept_list"`
}

And when initialized, I would have a "School ABC" in a sea of schools containing something that looks like below:

{
    "_id" : ObjectId("55fbb522022aae7b3a000003"),
    "school_name" : "School ABC",
    "dept_list" : [
        {
            "dept_name" : "Department A",
            "crse_list" : [
                {
                    "crse_name" : "Class A"
                },
                {
                    "crse_name" : "Class B"
                },
            ]
        }
    ]
}

For hours on end I couldn't find a solution that effectively works by given the school_name, dept_name, and crse_name:

Find the dept_list of school_name > find the crse_list of dept_name > find crse_name

The reason that such chain of finds are required is because the scope of the find should be limited to the school, and then the department. Logic and housekeeping happens after the each stages of finds.

I tried code such as

result := MIS_School{}

err := database.C("schools").Find(bson.M{"school_name": school}).Select(
bson.M{"dept_list": bson.M{"$elemMatch": bson.M{"dept_name": dept}}}).Select(
bson.M{"crse_list": bson.M{"$elemMatch": bson.M{"crse_name": crse}}}).One(&result)

But it didn't work since Select projections can't be chained in Mgo(?)

I have read from somewhere that mongodb doesn't have the capability to directly retrieve documents nested in arrays deeper than 1-2 levels (Getting Document C inside B array inside A array). Is that true? How could I work around this problem?

Thanks!

  • 写回答

2条回答 默认 最新

  • doudaifu6083 2015-09-18 19:20
    关注

    You can chain the Select statements, but the value of the second call will override the value of the first call, rather than doing what the example implies it does, which is to dive deeper into the nested structure.

    To achieve what apparently you are trying to do, you may use the aggregation framework to manipulate these nested objects in arbitrary ways.

    For example, this is a simple pipeline that would pull out the exact matching courses:

        pipeline := []bson.M{
                {"$match": bson.M{"school_name": school}},
                {"$unwind": "$dept_list"},
                {"$unwind": "$dept_list.crse_list"},
                {"$match": bson.M{
                         "dept_list.dept_name": dept,
                         "dept_list.crse_list.crse_name": crse,
                }},
        }
        iter := coll.Pipe(pipeline).Iter()
    

    You can use the resulting iterator the same way you use iterators from Find.

    For this pipeline, the resulting objects will look like:

        bson.M{
                "_id":"...",
                "dept_list": bson.M{
                        "dept_name": "Department A",   
                        "crse_list": bson.M{
                                "crse_name": "Class B",
                        }
                },
                "school_name":"School ABC",
        }
    

    You can change the shape of the resulting object in arbitrary ways, though. Have a look at the aggregation framework documentation for more details.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置
  • ¥15 有没有研究水声通信方面的帮我改俩matlab代码
  • ¥15 ubuntu子系统密码忘记
  • ¥15 保护模式-系统加载-段寄存器