MongoDB聚合:在不加入的情况下计算查找的结果

发布于 2025-01-21 03:40:56 字数 1348 浏览 0 评论 0原文

我正在处理此查询:

    customers.aggregate: [
  {$lookup: {
    from: "users",
    localField: "_id",
    foreignField: "customerId",
    as: "users"
  }}, 
  {$lookup: {
    from: "templates",
        let: {localField: "$_id"},
    pipeline: [{
    $match: { $and: [{
      $expr: { $eq: ["$customerId", "$$localField"]}},
        {module: false}]
    }}],
    as: "templates"
  }},
  {$lookup: {
    from: "publications",
    localField: "_id",
    foreignField: "customerId",
    as: "publications"
  }},
 {$lookup: {
    from: "documents",
    let: {localField: "$_id"},
    pipeline: [{
    $match: { $and: [{
      $expr: { $eq: ["$customerId", "$$localField"]}},
        {createdAt: {$gte: {$date: "<someDate>"}}}]
    }}],
    as: "recentDocuments"
  }}
]

在最后一个查找阶段,我是根据customerId根据_id字段字段来过滤文档的,而不是&lt; lyt&gt ;然后将这些文档加入到各个“客户”对象。 在此步骤之后,或者即使在同一步骤中,我也想在每个结果的“客户”文档中添加一个新字段,并使用“文档”中的所有文档数量(不仅是传递时间过滤器的文档)数量“用customerId字段值收集,与客户文档的_id相对应。而且我也希望不将这些文档加入客户对象,因为我只需要各自customerId的文档总数。我只能使用扩展JSON V1严格模式语法。 结果看起来像:

customers: [
 0: {
  users: [...],
  templates: [...],
  publications: [...],
  recentDocuments: [...],
  totalDocuments: <theCountedNumber>
 },
 1: {...},
 2: {...},
 ...
] 

I'm working with this query:

    customers.aggregate: [
  {$lookup: {
    from: "users",
    localField: "_id",
    foreignField: "customerId",
    as: "users"
  }}, 
  {$lookup: {
    from: "templates",
        let: {localField: "$_id"},
    pipeline: [{
    $match: { $and: [{
      $expr: { $eq: ["$customerId", "$localField"]}},
        {module: false}]
    }}],
    as: "templates"
  }},
  {$lookup: {
    from: "publications",
    localField: "_id",
    foreignField: "customerId",
    as: "publications"
  }},
 {$lookup: {
    from: "documents",
    let: {localField: "$_id"},
    pipeline: [{
    $match: { $and: [{
      $expr: { $eq: ["$customerId", "$localField"]}},
        {createdAt: {$gte: {$date: "<someDate>"}}}]
    }}],
    as: "recentDocuments"
  }}
]

In the last lookup stage I'm filtering documents with the customerId field according to the _id field and newer than <someDate> and then joining those documents to respective "customer" object.
And after this step or if possible even in this same step I would also like to add a new field to each resulting "customer" document with the counted number of all the documents (not only those that pass the time filter) from the "documents" collection with the customerId field value corresponding to the customer document's _id. And I also wish not to join those documents to the customer object as I only need a total number of documents with respective customerId. I can only use extended JSON v1 strict mode syntax.
The result would look like:

customers: [
 0: {
  users: [...],
  templates: [...],
  publications: [...],
  recentDocuments: [...],
  totalDocuments: <theCountedNumber>
 },
 1: {...},
 2: {...},
 ...
] 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挽梦忆笙歌 2025-01-28 03:40:56

使用 $set$size

db.customers.aggregate([
  {
    $lookup: {
      from: "documents",
      let: { localField: "$_id" },
      pipeline: [
        {
          $match: {
            $and: [
              { $expr: { $eq: [ "$customerId", "$localField" ] } }
            ]
          }
        }
      ],
      as: "recentDocuments"
    }
  },
  {
    $set: {
      totalDocuments: { $size: "$recentDocuments" }
    }
  }
])

mongoplayground

Use $set and $size

db.customers.aggregate([
  {
    $lookup: {
      from: "documents",
      let: { localField: "$_id" },
      pipeline: [
        {
          $match: {
            $and: [
              { $expr: { $eq: [ "$customerId", "$localField" ] } }
            ]
          }
        }
      ],
      as: "recentDocuments"
    }
  },
  {
    $set: {
      totalDocuments: { $size: "$recentDocuments" }
    }
  }
])

mongoplayground

盛夏已如深秋| 2025-01-28 03:40:56

所以周四我找到了解决我的问题的正确语法。它是这样的:

db.customers.aggregate([
    {
    $lookup: {
    from: "users",
    localField: "_id",
    foreignField: "customerId",
    as: "users"
  }}, 
  {$lookup: {
    from: "templates",
        let: {localField: "$_id"},
    pipeline: [{
    $match: { $and: [{
      $expr: { $eq: ["$customerId", "$localField"]}},
        {module: false}]
    }}],
    as: "templates"
  }},
  {$lookup: {
    from: "publications",
    localField: "_id",
    foreignField: "customerId",
    as: "publications"
  }},
  {$lookup: {
    from: "documents",
    let: {localField: "$_id"},
    pipeline: [{
    $match: { $and: [{
      $expr: { $eq: ["$customerId", "$localField"]}},
        {createdAt: {$gte: {$date: "<someDate>"}}}]
    }}],
    as: "recentDocuments"
  },
  {$lookup: {
    from: "documents",
    let: {localField: "$_id"},
    pipeline: [{
    $match: {$and: [{
      $expr: {$eq: ["$customerId", "$localField"]}},
      { $count: "count" }],
    as: "documentsNumber"
  }}
])

此命令将在聚合管道的最后阶段再次检查文档集合,但这一次将返回所有文档而不是按时间段进行过滤,然后将结果对象交换为每个“ customer”对象,其数组中的一项是所有文档的数量。该数组稍后可以使用 $unwind 操作“展开”,但事实证明它会大大降低性能,因此 - 被省略。我真的希望这能帮助有人解决类似的问题。

So on Thursday I've found a proper syntax to solve my problem. It goes like:

db.customers.aggregate([
    {
    $lookup: {
    from: "users",
    localField: "_id",
    foreignField: "customerId",
    as: "users"
  }}, 
  {$lookup: {
    from: "templates",
        let: {localField: "$_id"},
    pipeline: [{
    $match: { $and: [{
      $expr: { $eq: ["$customerId", "$localField"]}},
        {module: false}]
    }}],
    as: "templates"
  }},
  {$lookup: {
    from: "publications",
    localField: "_id",
    foreignField: "customerId",
    as: "publications"
  }},
  {$lookup: {
    from: "documents",
    let: {localField: "$_id"},
    pipeline: [{
    $match: { $and: [{
      $expr: { $eq: ["$customerId", "$localField"]}},
        {createdAt: {$gte: {$date: "<someDate>"}}}]
    }}],
    as: "recentDocuments"
  },
  {$lookup: {
    from: "documents",
    let: {localField: "$_id"},
    pipeline: [{
    $match: {$and: [{
      $expr: {$eq: ["$customerId", "$localField"]}},
      { $count: "count" }],
    as: "documentsNumber"
  }}
])

This command would, in the last stage of the aggregate pipeline, go over the documents collection again, but this time would return all the documents instead of filtering by the time period, and then would swap the resulting object for every "customer" object with the array with one item being the number of all the documents. The array could be later "unwinded" with the $unwind action, but it proved to decrease the performance drastically, thus - omitted. I really hope this will help someone to solve a similar problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文