【问题标题】:match subdocument within another subdocument same document在另一个子文档中匹配子文档相同的文档
【发布时间】:2015-08-19 12:57:47
【问题描述】:

我的收藏中有以下文件:

{
"_id": ObjectId('555a33d69487b45401ec1149'),
"nombre": "demo",
"roles": [
    {
        "id": ObjectId('556ca1999487009c1fac125f'),
        "nombre": "rol1"
    },
    {
        "id": ObjectId('556ca1a09487009c1fac1260'),
        "nombre": "rol2"
    },
    {
        "id": ObjectId('556ca1a69487009c1fac1261'),
        "nombre": "rol3"
    }
],
"usuarios": [
    {
        "id": ObjectId('556ca1de9487009c1fac1262'),
        "activo": true,
        "roles": [
            {
                "id": ObjectId('556ca1999487009c1fac125f')
            }
        ]
    },
    {
        "id": ObjectId('556ca2659487009c1fac1263'),
        "activo": true,
        "roles": [
            {
                "id": ObjectId('556ca1a09487009c1fac1260')
            }
        ]
    },
    {
        "id": ObjectId('556ca27a9487009c1fac1264'),
        "activo": true,
        "roles": [
            {
                "id": ObjectId('556ca1a69487009c1fac1261')
            }
        ]
    }
]
}


{
    "_id": ObjectId('556f457594877b4502b2e85d'),
    "nombre": "app3",
    "roles": [
        {
            "id": ObjectId('556f45fa94877b4502b2e864'),
            "nombre": "rol1_app3"
        },
        {
            "id": ObjectId('556f460194877b4502b2e865'),
            "nombre": "rol3_app3"
        },
        {
            "id": ObjectId('556f460694877b4502b2e866'),
            "nombre": "rol5_app3"
        },
        {
            "id": ObjectId('556f460b94877b4502b2e867'),
            "nombre": "rol7_app3"
        }
    ],
    "usuarios": [
        {
            "id": ObjectId('556ca1de9487009c1fac1262'),
            "activo": true,
            "roles": [
                {
                    "id": ObjectId('556f460b94877b4502b2e867')
                },
                {
                    "id": ObjectId('556f460194877b4502b2e865')
                }
            ]
        }
    ]
}

我想要的是指定 'usuarios.id' 并通过存在 'usuarios.id' 的每个文档获取所有的 "roles.id" 、 "roles.nombre"。

我已经试过了:

-- 首先声明一个带有我要查找的 'usuarios.id' 的 var

var uid = new ObjectId("556ca1de9487009c1fac1262")

然后我执行这个:

db.aplicacion.aggregate([
{ $match: { "usuarios.id" : uid, "usuarios.activo" : true } },
{ $unwind: "$usuarios"},
{ $unwind: "$usuarios.roles"},
{ $match: { "usuarios.id" : uid } },
{ $unwind: "$roles"},
{ $project: { "nombre":1, "usuarios.roles.id":1 , "usuarios.id":1,      "roles.id":1, "roles.nombre":1 }}
]).pretty();

但结果是这样的:

    {
        "_id" : ObjectId("555a33d69487b45401ec1149"),
        "nombre" : "demo",
        "roles" : {
                "id" : ObjectId("556ca1999487009c1fac125f"),
                "nombre" : "rol1"
        },
        "usuarios" : {
                "id" : ObjectId("556ca1de9487009c1fac1262"),
                "roles" : {
                        "id" : ObjectId("556ca1999487009c1fac125f")
                }
        }
}
{
        "_id" : ObjectId("555a33d69487b45401ec1149"),
        "nombre" : "demo",
        "roles" : {
                "id" : ObjectId("556ca1a09487009c1fac1260"),
                "nombre" : "rol2"
        },
        "usuarios" : {
                "id" : ObjectId("556ca1de9487009c1fac1262"),
                "roles" : {
                        "id" : ObjectId("556ca1999487009c1fac125f")
                }
        }
}
{
        "_id" : ObjectId("555a33d69487b45401ec1149"),
        "nombre" : "demo",
        "roles" : {
                "id" : ObjectId("556ca1a69487009c1fac1261"),
                "nombre" : "rol3"
        },
        "usuarios" : {
                "id" : ObjectId("556ca1de9487009c1fac1262"),
                "roles" : {
                        "id" : ObjectId("556ca1999487009c1fac125f")
                }
        }
}
{
        "_id" : ObjectId("556f457594877b4502b2e85d"),
        "nombre" : "app3",
        "roles" : {
                "id" : ObjectId("556f45fa94877b4502b2e864"),
                "nombre" : "rol1_app3"
        },
        "usuarios" : {
                "id" : ObjectId("556ca1de9487009c1fac1262"),
                "roles" : {
                        "id" : ObjectId("556f460b94877b4502b2e867")
                }
        }
}
{
        "_id" : ObjectId("556f457594877b4502b2e85d"),
        "nombre" : "app3",
        "roles" : {
                "id" : ObjectId("556f460194877b4502b2e865"),
                "nombre" : "rol3_app3"
        },
        "usuarios" : {
                "id" : ObjectId("556ca1de9487009c1fac1262"),
                "roles" : {
                        "id" : ObjectId("556f460b94877b4502b2e867")
                }
        }
}
{
        "_id" : ObjectId("556f457594877b4502b2e85d"),
        "nombre" : "app3",
        "roles" : {
                "id" : ObjectId("556f460694877b4502b2e866"),
                "nombre" : "rol5_app3"
        },
        "usuarios" : {
                "id" : ObjectId("556ca1de9487009c1fac1262"),
                "roles" : {
                        "id" : ObjectId("556f460b94877b4502b2e867")
                }
        }
}
{
        "_id" : ObjectId("556f457594877b4502b2e85d"),
        "nombre" : "app3",
        "roles" : {
                "id" : ObjectId("556f460b94877b4502b2e867"),
                "nombre" : "rol7_app3"
        },
        "usuarios" : {
                "id" : ObjectId("556ca1de9487009c1fac1262"),
                "roles" : {
                        "id" : ObjectId("556f460b94877b4502b2e867")
                }
        }
}
{
        "_id" : ObjectId("556f457594877b4502b2e85d"),
        "nombre" : "app3",
        "roles" : {
                "id" : ObjectId("556f45fa94877b4502b2e864"),
                "nombre" : "rol1_app3"
        },
        "usuarios" : {
                "id" : ObjectId("556ca1de9487009c1fac1262"),
                "roles" : {
                        "id" : ObjectId("556f460194877b4502b2e865")
                }
        }
}
{
        "_id" : ObjectId("556f457594877b4502b2e85d"),
        "nombre" : "app3",
        "roles" : {
                "id" : ObjectId("556f460194877b4502b2e865"),
                "nombre" : "rol3_app3"
        },
        "usuarios" : {
                "id" : ObjectId("556ca1de9487009c1fac1262"),
                "roles" : {
                        "id" : ObjectId("556f460194877b4502b2e865")
                }
        }
}
{
        "_id" : ObjectId("556f457594877b4502b2e85d"),
        "nombre" : "app3",
        "roles" : {
                "id" : ObjectId("556f460694877b4502b2e866"),
                "nombre" : "rol5_app3"
        },
        "usuarios" : {
                "id" : ObjectId("556ca1de9487009c1fac1262"),
                "roles" : {
                        "id" : ObjectId("556f460194877b4502b2e865")
                }
        }
}
{
        "_id" : ObjectId("556f457594877b4502b2e85d"),
        "nombre" : "app3",
        "roles" : {
                "id" : ObjectId("556f460b94877b4502b2e867"),
                "nombre" : "rol7_app3"
        },
        "usuarios" : {
                "id" : ObjectId("556ca1de9487009c1fac1262"),
                "roles" : {
                        "id" : ObjectId("556f460194877b4502b2e865")
                }
        }
}

这是每个 rol.id 的产物,我期望得到的是这样的(只得到那些角色.id = usuarios.roles.id 的:

    {
        "_id" : ObjectId("555a33d69487b45401ec1149"),
        "nombre" : "demo",
        "roles" : {
                "id" : ObjectId("556ca1999487009c1fac125f"),
                "nombre" : "rol1"
        },
        "usuarios" : {
                "id" : ObjectId("556ca1de9487009c1fac1262"),
                "roles" : {
                        "id" : ObjectId("556ca1999487009c1fac125f")
                }
        }
},
{
        "_id" : ObjectId("556f457594877b4502b2e85d"),
        "nombre" : "app3",
        "roles" : {
                "id" : ObjectId("556f460b94877b4502b2e867"),
                "nombre" : "rol7_app3"
        },
        "usuarios" : {
                "id" : ObjectId("556ca1de9487009c1fac1262"),
                "roles" : {
                        "id" : ObjectId("556f460b94877b4502b2e867")
                }
        }
},
{
        "_id" : ObjectId("556f457594877b4502b2e85d"),
        "nombre" : "app3",
        "roles" : {
                "id" : ObjectId("556f460194877b4502b2e865"),
                "nombre" : "rol3_app3"
        },
        "usuarios" : {
                "id" : ObjectId("556ca1de9487009c1fac1262"),
                "roles" : {
                        "id" : ObjectId("556f460194877b4502b2e865")
                }
        }
}

有什么想法吗??

这是我当前的脚本:

var uid = new ObjectId("556ca1de9487009c1fac1262")

db.aplicacion.aggregate([
    { $match: { "usuarios.id" : uid, "usuarios.activo" : true } },
    { $unwind: "$usuarios"},
    { $unwind: "$usuarios.roles"},
    { $match: { "usuarios.id" : uid } },
    { $unwind: "$roles"},
    { $project: { "nombre":1, "usuarios.roles.id":1 , "usuarios.id":1,      "roles.id":1, "roles.nombre":1 }}
    ]).pretty();

更新:

使用@yogesh 解决方案后,我对脚本做了一点改进:

    db.coll.aggregate({
    "$unwind": "$usuarios"
}, {
    "$match": {
        "usuarios.id": ObjectId("556ca1de9487009c1fac1262"),
        "usuarios.activo":true,
    }
}, {
    "$unwind": "$usuarios.roles"
}, {
    "$unwind": "$roles"
}, {
    "$project": {
        "nombre": 1,
        "roles.id": 1,
        "roles.nombre": 1,        
        "roles.activo": 1,
        "matched": {
            "$eq": ["$roles.id", "$usuarios.roles.id"], //macthed roles.id == usuarios.roles.id            
        }
    }
}, {
    "$match": {
        "matched": true,
        "roles.activo" : true
    }
},
{
  $group : {
        _id : "$_id",
        nombre: { $first: "$nombre" },
        roles : {
                $push : "$roles"
        }

  }
}).pretty();

添加了一个 $group,我认为结果具有更好的结构:

    {
        "_id" : ObjectId("556f457594877b4502b2e85d"),
        "nombre" : "app3",
        "roles" : [
                {
                        "id" : ObjectId("556f460b94877b4502b2e867"),
                        "nombre" : "rol7_app3",
                        "activo" : true
                },
                {
                        "id" : ObjectId("556f460194877b4502b2e865"),
                        "nombre" : "rol3_app3",
                        "activo" : true
                }
        ]
}
{
        "_id" : ObjectId("555a33d69487b45401ec1149"),
        "nombre" : "demo",
        "roles" : [
                {
                        "id" : ObjectId("556ca1999487009c1fac125f"),
                        "nombre" : "rol1",
                        "activo" : true
                }
        ]
}

再次感谢@yogesh

【问题讨论】:

    标签: mongodb match project subdocument


    【解决方案1】:

    您的聚合遗漏了一些您应该在 projectmacthed roles.id == usuarios.roles.id 中匹配的内容,请查看以下聚合:

    db.collectionName.aggregate({
        "$unwind": "$usuarios"
    }, {
        "$match": {
            "usuarios.id": ObjectId("556ca1de9487009c1fac1262")
        }
    }, {
        "$unwind": "$usuarios.roles"
    }, {
        "$unwind": "$roles"
    }, {
        "$project": {
            "nombre": 1,
            "roles": 1,
            "usuarios.id": 1,
            "usuarios.activo": 1,
            "usuarios.roles.id": 1,
            "matched": {
                "$eq": ["$roles.id", "$usuarios.roles.id"] //macthed roles.id == usuarios.roles.id
            }
        }
    }, {
        "$match": {
            "matched": true
        }
    }).pretty()
    

    【讨论】:

      猜你喜欢
      • 2017-06-13
      • 2015-02-10
      • 2016-12-14
      • 2011-09-26
      • 1970-01-01
      • 2015-10-31
      • 1970-01-01
      • 2019-01-16
      • 1970-01-01
      相关资源
      最近更新 更多