具有3个级别的MongoDB嵌套查找 [英] MongoDB nested lookup with 3 levels
问题描述
我需要从数据库中以JSON检索整个单个对象层次结构.实际上,关于实现此结果的任何其他解决方案的建议将被高度推荐.我决定使用具有$ lookup支持的MongoDB.
I need to retrieve the entire single object hierarchy from the database as a JSON. Actually the proposal about any other solution to achive this result would be highly appriciated. I decided to use MongoDB with its $lookup support.
所以我有三个收藏夹:
聚会
{ "_id" : "2", "name" : "party2" }
{ "_id" : "5", "name" : "party5" }
{ "_id" : "4", "name" : "party4" }
{ "_id" : "1", "name" : "party1" }
{ "_id" : "3", "name" : "party3" }
地址
{ "_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" }
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" }
我需要检索所有具有所有相应地址和地址注释的各方,作为记录的一部分.我的汇总:
I need to retrieve all parties with all corresponding addresses and address comments as part of the record. My aggregation:
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"
}
}])
结果很奇怪.某些记录还可以.但是缺少_id 4的Party(没有地址).另外,结果集中有两个Party _id 1(但地址不同):
The result is pretty weird. Some records are ok. But Party with _id 4 is missing (there is no address for it). Also there are two Party _id 1 in the result set (but with different addresses):
{
"_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"
}]
}
}
请帮助我.我对MongoDB相当陌生,但是我觉得它可以满足我的需求.
Please help me with this. I'm pretty new to the MongoDB but I feel it can do what I need from it.
推荐答案
麻烦"的原因是第二个汇总阶段-{ $unwind: "$address" }
.它将删除具有_id: 4
的一方的记录(因为您的地址数组为空,如您所提到的),并为具有_id: 1
和_id: 5
的一方生成两条记录(因为它们每个都有两个地址).
The cause of your 'troubles' is the second aggregation stage - { $unwind: "$address" }
. It removes record for party with _id: 4
(because its address array is empty, as you mention) and produces two records for parties _id: 1
and _id: 5
(because each of them has two addresses).
To prevent removing of parties without addresses you should set
preserveNullAndEmptyArrays
option of$unwind
stage totrue
.
为防止当事方重复其不同地址,您应该添加 $group
聚集到您的管道中.另外,将 $project
阶段与
To prevent duplicating of parties for its different addresses you should add $group
aggregation stage to your pipeline. Also, use $project
stage with $filter
operator to exclude empty address records in output.
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] } }
}
}
}]);
这篇关于具有3个级别的MongoDB嵌套查找的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!