【问题标题】:How to use aggregate in mongoosejs with this example如何通过此示例在 mongoosejs 中使用聚合
【发布时间】:2020-06-08 21:45:50
【问题描述】:

我是来问一个关于mongo聚合函数实现这个例子的问题。

场景

我有 3 个 Mongo 模式,即房子、家庭和教育,它们是:

House: {
_id: ObjectId,
state: Number,
houseNumber: Number
}

Family: {
    _id: ObjectId,
    houseId: ObjectId,//ref: house
    name: String,
    gender: String
}

Education: {
    _id: ObjectId,
    familyId: ObjectId,//ref: Family
    level: String, //might be one of ["primary","secondary","higher_secondary"]
}

预期输出:

{
    state1: {
        primary: {
            male: 3,
            female: 4   
        },
        secondary: {
            male: 4,
            female: 8
        }
    },
    state2: {
        primary: {
            male: 5,
            female: 4   
        },
        secondary: {
            male: 4,
            female: 6
        }
    }
}

我想按性别和病房对所有教育水平进行分组。

我做了什么:

我是 mongo 世界的新手,最近从 sql 转到 no-sql。我已经这样做了:

let edu = await Education.find({level: "primary"}).populate({
      path: "family",
      match: {gender: "male"},
      select: "house",
      populate: {
        path: "house",
        match: {state: 1},
        select: "_id"
      }
    });
let count = (await edu.filter(each => !isEmpty(each.family) && !isEmpty(each.family.house)).length) || 0;

通过这样做,我得到了从状态 1 学习小学的男性成员的数量。但我不能为每个数据一个一个地调用这个函数。

根据要求,样本数据为:

house = [
  {
    _id: AA1,
    state: 1,
    houseNumber: 101
  },
  {
    _id: AA2,
    state: 1,
    houseNumber: 102
  },
  {
    _id: AA3,
    state: 2,
    houseNumber: 201
  }
];

family = [
  {
    _id: BB1,
    houseId: AA1, //ref: house
    name: "John",
    gender: "male"
  },
  {
    _id: BB2,
    houseId: AA1, //ref: house
    name: "Solena",
    gender: "female"
  },
  {
    _id: BB3,
    houseId: AA2, //ref: house
    name: "Efrain",
    gender: "male"
  },
  {
    _id: BB4,
    houseId: AA3, //ref: house
    name: "Naruto",
    gender: "male"
  }
];


education = [
  {
    _id: CC1,
    familyId: AA1, //ref: Family
    level: "primary"
  },
  {
    _id: CC2,
    familyId: AA2, //ref: Family
    level: "secondary"
  },
  {
    _id: CC3,
    familyId: AA3, //ref: Family
    level: "primary"
  },
  {
    _id: CC4,
    familyId: AA4, //ref: Family
    level: "secondary"
  }
];

P.S 预期输出与样本数据无关。并且 ObjectId 已被替换为一些唯一的引用。

这里有什么线索吗?

【问题讨论】:

  • 您能否举例说明哪些数据存储到这些集合中?或发送样品
  • 能否在你的问题中放一个小数据集
  • 在您的 House 文档中没有 state 字段,您可以编辑您的问题吗?
  • 非常感谢!我添加了一些示例数据。

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


【解决方案1】:

您可以在 4.x 版本中使用以下聚合查询。

查询家庭收藏并加入教育收藏获得等级,然后加入房屋收藏获得状态。

一旦您拥有按州、级别和性别划分的所有数据组,就可以计算所有匹配项,然后是其他组以格式化结果。最后阶段将聚合结果推广到自己的文档中。

最后两组将上一阶段的结果格式化为命名的键值文档。第一组将结果格式化为按州分组的性别和计数。第二组格式化先前组合的性别并使用教育键进行计数。

最后用状态键替换根阶段以格式化组合的性别、计数和教育文档。

为了清晰起见,还在每个阶段之后添加了输出。

db.family.aggregate(
[
  {"$lookup":{
    "from":"education",
    "localField":"_id",
    "foreignField":"familyId",
    "as":"education"
  }},
  {"$unwind":"$education"},
  {"$lookup":{
    "from":"house",
    "localField":"houseId",
    "foreignField":"_id",
    "as":"state"
  }},
  {"$unwind":"$state"},
  {"$group":{
    "_id":{
      "state":"$state.state",
      "education":"$education.level",
      "gender":"$gender"
    },
    "count":{"$sum":1}
  }},//{"_id":{"state" :1,"education" :"secondary","gender":"female"},"count":1}
  {"$group":{
    "_id":{"state":"$_id.state","education":"$_id.education"},
    "gandc":{"$mergeObjects":{"$arrayToObject":[[["$_id.gender","$count"]]]}}
  }},//{"_id":{"state":1,"education":"primary"},"gandc":{"male":2}}
  {"$group":{
    "_id":"$_id.state",
    "egandc":{"$mergeObjects":{"$arrayToObject":[[["$_id.education","$gandc"]]]}}
  }},//{"_id":1,"egandc":{"primary":{"male":2},"secondary":{"female":1}}}
  {"$replaceRoot":{"newRoot":{"$arrayToObject":[[[{"$toString":"$_id"},"$egandc"]]]}}} ])
])
//{"1":{"primary":{"male" : 2 },"secondary":{"female":1}}}

【讨论】:

  • 您好,先生。非常感谢你的工作。我一直在研究猫鼬,我不敢问你如何获得第一个变量 db?我如何导入以及它与 npm 的依赖关系是什么?
  • 不客气。这是 shell 查询(可以从 mongo cli 中按原样运行)。对于猫鼬,您可以使用 Family.aggregate(在 () 中复制查询) 假设您在某处定义了家庭模型。这里的例子mongoosejs.com/docs/api/aggregate.html
  • 是的,我已经这样做了,mongoose 没有找到 $mergeObjects ` MongoError: unknown group operator '$mergeObjects'`。
  • 看起来您使用的是旧版本。你需要 4.x mongo 版本。最新版本是 4.2。看看能不能升级。请检查 mongo 服务器版本而不是 mongoose lib 版本。
  • 我升级了 mongo 服务器版本,但它仍然显示 MongoError: unknown group operator '$mergeObjects.我有 mongo 服务器版本:4.2,mongoose:5.9.2 和 mongodb 驱动程序:3.5.4
猜你喜欢
  • 2012-10-18
  • 1970-01-01
  • 2020-01-26
  • 1970-01-01
  • 2021-09-12
  • 2011-12-19
  • 1970-01-01
  • 2012-06-29
  • 1970-01-01
相关资源
最近更新 更多