Yur*_*riy 29 lookup mongodb mongodb-query aggregation-framework
我需要从数据库中检索整个单个对象层次结构作为JSON.实际上关于实现这一结果的任何其他解决方案的提议将受到高度关注.我决定使用MongoDB及其$ lookup支持.
所以我有三个系列:
派对
{ "_id" : "2", "name" : "party2" }
{ "_id" : "5", "name" : "party5" }
{ "_id" : "4", "name" : "party4" }
{ "_id" : "1", "name" : "party1" }
{ "_id" : "3", "name" : "party3" }
Run Code Online (Sandbox Code Playgroud)
地址
{ "_id" : "a3", "street" : "Address3", "party_id" : "2" }
{ "_id" : "a6", "street" : "Address6", "party_id" : "5" }
{ "_id" : "a1", "street" : "Address1", "party_id" : "1" }
{ "_id" : "a5", "street" : "Address5", "party_id" : "5" }
{ "_id" : "a2", "street" : "Address2", "party_id" : "1" }
{ "_id" : "a4", "street" : "Address4", "party_id" : "3" }
Run Code Online (Sandbox Code Playgroud)
addressComment
{ "_id" : "ac2", "address_id" : "a1", "comment" : "Comment2" }
{ "_id" : "ac1", "address_id" : "a1", "comment" : "Comment1" }
{ "_id" : "ac5", "address_id" : "a5", "comment" : "Comment6" }
{ "_id" : "ac4", "address_id" : "a3", "comment" : "Comment4" }
{ "_id" : "ac3", "address_id" : "a2", "comment" : "Comment3" }
Run Code Online (Sandbox Code Playgroud)
我需要检索具有所有相应地址的所有方,并将注释作为记录的一部分.我的聚合:
db.party.aggregate([{
$lookup: {
from: "address",
localField: "_id",
foreignField: "party_id",
as: "address"
}
},
{
$unwind: "$address"
},
{
$lookup: {
from: "addressComment",
localField: "address._id",
foreignField: "address_id",
as: "address.addressComment"
}
}])
Run Code Online (Sandbox Code Playgroud)
结果非常奇怪.有些记录还可以.但是没有_id 4的派对(没有地址).结果集中还有两个Party _id 1(但具有不同的地址):
{
"_id": "1",
"name": "party1",
"address": {
"_id": "2",
"street": "Address2",
"party_id": "1",
"addressComment": [{
"_id": "3",
"address_id": "2",
"comment": "Comment3"
}]
}
}{
"_id": "1",
"name": "party1",
"address": {
"_id": "1",
"street": "Address1",
"party_id": "1",
"addressComment": [{
"_id": "1",
"address_id": "1",
"comment": "Comment1"
},
{
"_id": "2",
"address_id": "1",
"comment": "Comment2"
}]
}
}{
"_id": "3",
"name": "party3",
"address": {
"_id": "4",
"street": "Address4",
"party_id": "3",
"addressComment": []
}
}{
"_id": "5",
"name": "party5",
"address": {
"_id": "5",
"street": "Address5",
"party_id": "5",
"addressComment": [{
"_id": "5",
"address_id": "5",
"comment": "Comment5"
}]
}
}{
"_id": "2",
"name": "party2",
"address": {
"_id": "3",
"street": "Address3",
"party_id": "2",
"addressComment": [{
"_id": "4",
"address_id": "3",
"comment": "Comment4"
}]
}
}
Run Code Online (Sandbox Code Playgroud)
请帮我解决一下这个.我对MongoDB很新,但我觉得它可以做我需要的东西.
Sha*_*had 47
你的"麻烦"的原因是第二个聚合阶段 - { $unwind: "$address" }.它消除了党的纪录_id: 4(因为它的地址数组为空,你提到),以及各方产生两个记录_id: 1和_id: 5(因为他们每个人都有两个地址).
要防止删除没有地址的参与方,您应该将stage preserveNullAndEmptyArrays选项设置$unwind为true.
为防止对不同地址的各方进行重复,您应该$group为管道添加聚合阶段.另外,使用$projectstage with $filteroperator来排除输出中的空地址记录.
db.party.aggregate([{
$lookup: {
from: "address",
localField: "_id",
foreignField: "party_id",
as: "address"
}
}, {
$unwind: {
path: "$address",
preserveNullAndEmptyArrays: true
}
}, {
$lookup: {
from: "addressComment",
localField: "address._id",
foreignField: "address_id",
as: "address.addressComment",
}
}, {
$group: {
_id : "$_id",
name: { $first: "$name" },
address: { $push: "$address" }
}
}, {
$project: {
_id: 1,
name: 1,
address: {
$filter: { input: "$address", as: "a", cond: { $ifNull: ["$$a._id", false] } }
}
}
}]);
Run Code Online (Sandbox Code Playgroud)
Ash*_*shh 24
使用mongodb 3.6及更高版本的$lookup语法,无需使用即可轻松连接嵌套字段$unwind。
db.party.aggregate([
{ "$lookup": {
"from": "address",
"let": { "partyId": "$_id" },
"pipeline": [
{ "$match": { "$expr": { "$eq": ["$party_id", "$$partyId"] }}},
{ "$lookup": {
"from": "addressComment",
"let": { "addressId": "$_id" },
"pipeline": [
{ "$match": { "$expr": { "$eq": ["$address_id", "$$addressId"] }}}
],
"as": "address"
}}
],
"as": "address"
}},
{ "$unwind": "$address" }
])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
21408 次 |
| 最近记录: |