Mongodb 执行类似于同一文档中两个数组之间的外部联接的查询
给定以下集合结构:Mongodb 执行类似于同一文档中两个数组之间的外部联接的查询,mongodb,Mongodb,给定以下集合结构: db.two_lists.insert( { "addresses":[ { "studentId":1111, "addr":"1234 N Oak St.", "city":"Chicago", "state":"IL", "zipcode":60601 }, {
db.two_lists.insert(
{
"addresses":[
{
"studentId":1111,
"addr":"1234 N Oak St.",
"city":"Chicago",
"state":"IL",
"zipcode":60601
},
{
"studentId":3333,
"addr":"1234 N Oak St.",
"city":"Chicago",
"state":"IL",
"zipcode":60601
}
],
"students":[
{
"id":1111,
"name":'Frank Smith'
},
{
"id":2222,
"name":'Joe Smith'
}
]
}
);
我正试图返回一份学生名单和他们相应的地址。问题是这两个存储在不同的数组中。我需要学生ID来匹配它们。我找到了一种方法:
db.two_lists.aggregate([
{$match:{}}
,{$unwind:"$students"}
,{$unwind:"$addresses"}
,{$project:{ addresses:1, students:1,
sameId : {$cond: { if: { $eq: [ "$addresses.studentId", '$students.id' ] }, then: true, else: false }}}
}
,{$match:{sameId:true}}
]);
不幸的是,我的查询排除了没有地址的学生(studentId:2222)。如何最好地处理这样的问题。更改集合结构不是一个选项
预期产量
{
"result" : [
{
"_id" : ObjectId("567b6f3aba874c0b52280d49"),
"addresses" : {
"studentId" : 1111,
"addr" : "1234 N Oak St.",
"city" : "Chicago",
"state" : "IL",
"zipcode" : 60601
},
"students" : {
"id" : 1111,
"name" : "Frank Smith"
}
},
{
"students" : {
"id" : 2222,
"name" : "Joe Smith"
}
}
],
"ok" : 1
}
我找到了解决办法:
db.two_lists.aggregate([
{$match:{}}
,{$unwind:"$students"}
,{$unwind:"$addresses"}
,{$project:{ students:1,
addresses : {$cond: { if: { $eq: [ "$addresses.studentId", "$students.id" ] }, then: "$addresses", else: null }}}
}
,{$group:{_id:{students:"$students"}, addresses:{$addToSet:"$addresses"}}}
]);
给了我很多我想要的结果:
{
"result" : [
{
"_id" : {
"students" : {
"id" : 2222,
"name" : "Joe Smith"
}
},
"addresses" : [
null
]
},
{
"_id" : {
"students" : {
"id" : 1111,
"name" : "Frank Smith"
}
},
"addresses" : [
null,
{
"studentId" : 1111,
"addr" : "1234 N Oak St.",
"city" : "Chicago",
"state" : "IL",
"zipcode" : 60601
}
]
}
],
"ok" : 1
}
很高兴看到插入脚本作为问题的一部分发布。你能不能发布一个预期的输出结构,这将是一个巨大的问题。问题是一般的数据模型。只需为每个学生创建一个文档,连同他的地址和鲍勃的叔叔:没有BSON大小限制,没有不必要的复杂查询。@Batshray只是添加了我想要的输出。@MarkusWMahlberg同意,但正如我已经说过的,更改它不是一个选项。