Mongoose要求提供未被其他文件引用的文件

时间:2018-01-11 10:47:09

标签: node.js mongodb mongoose mongodb-query aggregation-framework

我使用MongoDB和Mongoose有以下集合结构:

const UserSchema = 
{
  "name": {
    "type": "String",
    "required": true,
    "unique": true
  },
  "company_id": {
    "type": "ObjectId"
    "ref": "Company"
    "required": true
   }

const CompanySchema = 
{
  "name": {
    "type": "String",
    "required": true,
    "unique": true
  },
  "ein": {
    "type": "String"
  }
}

获得所有未被任何用户引用的公司(所有没有用户的公司)的最快方法是什么?

我的第一次尝试是:

User.find({}).exec()
.then(users => {
    Company.find({ id: { $in: users}}).exec()
})
.then(companiesWithoutRefs => {
    return companiesWithoutRefs;
})
.catch(err => {
   throw new err;
});

问题:

  1. 承诺的结构是否正确?

  2. 我是否需要将$ in:users语句转换为ObjectId?如何使用多个值?

  3. 最后也是最重要的一个:

    1. 有没有办法在不完全加载User集合的情况下执行此查询,这更聪明?
    2. 感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

更好的方法是使用aggregation framework并应用 $lookup 管道阶段对相关数据进行查找,然后您可以通过检查查询看看返回的数组中是否存在任何元素:

Company.aggregate([
    {
        "$lookup": {
            "from": "users",
            "localField": "_id",
            "foreignField": "company_id",
            "as": "company_users"
        }
    },
    { "$match": { "company_users.0": { "$exists": false } } }
]).exec().then(res.json)

答案 1 :(得分:1)

我改进了您的查询

User.find({}).exec()
.then(users => {
    let companyIds = users.map(o => o.company_id);
    return Company.find({ id: { $nin: companyIds}}).exec()
})
.then(companiesWithoutRefs => {
    return companiesWithoutRefs;
})
.catch(err => {
   throw new err;
});
  1. 您的结构是正确的,但您的查询不是。
  2. 由于您的架构设计,您必须触发两个查询。对于一个查询,您可以使用子文档的概念