在同一文档的另一个子文档中匹配子文档
match subdocument within another subdocument same document
我的 collection 中有以下文件:
{
"_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 的产物,我希望得到的是这样的东西(只得到那些 roles.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
你的聚合遗漏了一些你应该在 project
到 macthed 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()
我的 collection 中有以下文件:
{
"_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 的产物,我希望得到的是这样的东西(只得到那些 roles.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
你的聚合遗漏了一些你应该在 project
到 macthed 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()