我有什么:
我在mongo中有一个有很多文档的集合。该集合称为Users
。出于示例目的,我已经显示了7条记录。
{
_id: _______________________,
name: Mary
},
{
_id: _______________________,
name: John,
manager: objectId("id of Mary");
},
{
_id: _______________________,
name: Tim,
manager: objectId("id of John");
},
{
_id: _______________________,
name: Tom,
manager: objectId("id of John");
},
{
_id: _______________________,
name: Henry,
manager: objectId("id of Tim");
},
{
_id: _______________________,
name: Mark,
manager: objectId("id of Henry");
},
{
_id: _______________________,
name: Todd,
manager: objectId("id of Mary");
}
通过查看上述数据,您可以看到如下关系:
Mary
|
-------------------------------------
| |
John Todd
|
--------------------------
| |
Tim Tom
|
Henry
|
Mark
我想要的是什么:
我想要一个mongoose查询,它会返回包含其子项和子项的所有记录。所以,例如,如果我想让John下的所有用户都包括John,那么我的输出应该是这样的:
{
_id: _______________________,
name: John,
manager: objectId("id of Mary");
},
{
_id: _______________________,
name: Tim,
manager: objectId("id of John");
},
{
_id: _______________________,
name: Tom,
manager: objectId("id of John");
},
{
_id: _______________________,
name: Henry,
manager: objectId("id of Tim");
},
{
_id: _______________________,
name: Mark,
manager: objectId("id of Henry");
}
我不想要的内容:
我知道数据是关系型的,所以有些人可能会建议我应该使用关系数据库。但是现在我正在尝试学习mongodb和Node.js.所以,我想坚持使用mongodb。
我也知道可以拥有一个包含所有数据的集合:
var ManagerSchema = new Schema({
manager_name: String,
users: [users]
}
var UserSchema = new Schema({
user_name: String
})
但我不想要上面提到的东西。
我只想拥有一个集合,数据将是关系型的。
答案 0 :(得分:3)
您需要分3个阶段完成:
_id
$in
运算符在这里很有用代码:
const idOfjohn = '1234567890abcdef';
let john, children, grandchildren; // initialise variables
Users.findById(idOfjohn) // find John
.then(user => {
john = user; // assign to variable with wider scope
return Users.find({ manager: idOfjohn }); // find users whose manager is John
})
.then(users => {
children = users;
const childrenIDs = users.map(user => user._id); // make array of IDs
return Users.find({ manager: { $in: childrenIDs } }); // find users whose managers have John as a manager
})
.then(users => {
grandchildren = users;
const all = [john]
.concat(children)
.concat(grandchildren); // create a single array
console.log(all); // or do whatever
});
修改强>
OP澄清他需要n级后代。const { wrap } = require('co');
const findWithDescendants = wrap(function*(topUserId, generations) {
const topUser = yield Users.findById(topUserId); // get John himself
let users = [topUser]; // will hold all users
let ids = [topUserId]; // will hold IDs to search in
for (let i = 0; i < generations; i++) {
const thisLevelUsers = yield Users.find({ manager: { $in: ids } });
ids = thisLevelUsers.map(user => user._id); // replace with new IDs
users = users.concat(thisLevelUsers); // add new users
}
return users;
});
findWithDescendants(idOfjohn, 3)
.then(users => {
console.log(users); // or do whatever
});
注意:为了确保没有重复项,您可以使用Set
而不是users
,或的数组,您可以将每个用户添加到{{ 1}}逐个检查每一个users
数组中是否存在它们。