Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/35.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 用于获取集合中的子代和孙子代的Mongoose查询_Javascript_Node.js_Mongodb_Mongoose - Fatal编程技术网

Javascript 用于获取集合中的子代和孙子代的Mongoose查询

Javascript 用于获取集合中的子代和孙子代的Mongoose查询,javascript,node.js,mongodb,mongoose,Javascript,Node.js,Mongodb,Mongoose,我所拥有的: 我在mongo收集了很多文件。该集合称为Users。出于示例目的,我展示了所有的7条记录 { _id: _______________________, name: Mary }, { _id: _______________________, name: John, manager: objectId("id of Mary"); }, { _id: _______________________, name: Ti

我所拥有的:

我在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
})
但是我不想要上面提到的东西


我只希望只有一个集合,数据将是相关的。

您需要分三个阶段进行:

  • 首先通过查询John的
    \u id
  • 通过搜索以John的id作为其经理的用户来获取John的“孩子”
  • 通过查询所有拥有John的任何子女作为其经理的用户,获取John的“孙子女”。MongoDB
    $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
        });
    
    const{wrap}=require('co');
    const findWithDescents=wrap(函数*(topUserId,代){
    const topUser=yield Users.findById(topUserId);//获取John本人
    let users=[topUser];//将容纳所有用户
    let ids=[topUserId];//将保留要在其中搜索的ID
    for(设i=0;iuser.\u id);//替换为新id
    users=users.concat(thisLevelUsers);//添加新用户
    }
    返回用户;
    });
    FindWith后代(idOfjohn,3)
    。然后(用户=>{
    console.log(用户);//或执行任何操作
    });
    

    注意:为确保不存在重复项,您可以为
    用户
    使用类似于数组的内容,也可以将每个用户逐个添加到
    用户
    ,检查每个操作符是否已经出现在
    用户
    数组中。

    看看mongodb 3.4I中引入的操作符,我还没有使用graphLookup,这可能是最好的解决方案。否则,我认为唯一可以做到这一点的方法是在单独的查询中进行查询,如果您愿意,我可以提供帮助。@felix我已经在文档中查看了图形查找。在我看来,图形查找返回的是继承人的体系结构数据。但我想要问题中提到的平面数据。@Aron我想看看你的答案。@Vishal我的答案有用吗?我希望它适用于第N个孩子。所以我不认为我会使用你给出的代码。谢谢你的帮助。我更新了我的答案以检索n个级别的深层次。谢谢你的编辑。我将检查它并告诉您是否需要任何更改/如果在const topUser=..之后在findWithDescents函数中输入console.log(topUser),那么我将获得John的所有直接子代。但就在returnusers语句之前,如果我是console.log(users);那么我就不会让任何用户登录。控制台中没有错误。我不知道为什么它会这样做。好的,我会尝试自己实现它。但是为什么我得到两个数组呢?我的意思是输出的模式是:
    [[{Tim object},{Tom object}],{Tim object},{Tom object},{Henry object}]
    。我还没有插入
    标记
    记录。还有一件事。输出中没有约翰的记录。