MongoDB Mongoose 按日期范围查询深层嵌套的子文档数组

2024-04-04

我有一个问题是与另一个问题类似 https://stackoverflow.com/questions/40971909/mongodb-mongoose-querying-an-array-of-objects-by-date但不完全相同,因为我的数据结构嵌套得更深,并且接受的答案没有解决问题。

技术:MongoDB 3.6、Mongoose 5.5、NodeJS 12

我正在尝试查询深层嵌套的对象数组。该查询将接受用户的“开始日期”和“结束日期”。项目报告是一个子文档数组,其中包含另一个子文档“工作完成者”数组。所有在开始和结束日期范围内具有“CompletedDate”的 WorkDoneBy 对象都应与其他几个属性一起返回。

期望的返回属性:

RecordID、RecordType、状态、ItemReport.WorkDoneBy.DateCompleted、ItemReport.WorkDoneBy.CompletedHours、ItemReport.WorkDoneBy.Person

记录架构:

let RecordsSchema = new Schema({
  RecordID: {
    type: Number,
    index: true
  },
  RecordType: {
    type: String,
    enum: ['Item', 'OSW']
  },
  Status: {
    type: String
  },
  // ItemReport array of subdocuments
  ItemReport: [ItemReportSchema],
}, {
  collection: 'records',
  selectPopulatedPaths: false
});

let ItemReportSchema = new Schema({
  // ObjectId reference
  ReportBy: {
    type: Schema.Types.ObjectId,
    ref: 'people'
  },
  ReportDate: {
    type: Date,
    required: true
  },
  WorkDoneBy: [{
    Person: {
      type: Schema.Types.ObjectId,
      ref: 'people'
    },
    CompletedHours: {
      type: Number,
      required: true
    },
    DateCompleted: {
      type: Date
    }
  }],
});

尝试1:

db.records.aggregate([
    {
        "$match": {
            "ItemReport.WorkDoneBy.DateCompleted": { "$gt": new Date("2017-01-01T12:00:00.000Z"), "$lt": new Date("2018-12-31T12:00:00.000Z") }
        }
    },
    {
        "$project": {
            "ItemReport.WorkDoneBy": {
                "$filter": {
                    "input": "$ItemReport.WorkDoneBy",
                    "as": "value",
                    "cond": {
                        "$and": [
                            { "$ne": [ "$$value.DateCompleted", null ] },
                            { "$gt": [ "$$value.DateCompleted", new Date("2017-01-01T12:00:00.000Z") ] },
                            { "$lt": [ "$$value.DateCompleted", new Date("2018-12-31T12:00:00.000Z") ] }
                        ]
                    }
                }
            }
        }
    }
])

尝试 1 返回:

{ "_id" : ObjectId("5dcb6406e63830b7aa54269d"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa5426fb"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa542708"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa542712"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }

期望的回报(为简洁起见删除了 _id):

请注意,仅当 WorkDoneBy 数组中的对象位于指定日期范围内时,才应返回它们。例如,RecordID 9018 ItemReport.WorkDoneBy 实际上具有 2016 年的日期,但不会返回这些日期,因为它们不在指定的日期范围内。

{ "ItemReport" : [ { "WorkDoneBy" : [ { "CompletedHours" : 11, "DateCompleted" : ISODate("2017-09-29T04:00:00Z"), "Person" : ObjectId("5dcb6409e63830b7aa54fd6e") }, { "CompletedHours" : 36, "DateCompleted" : ISODate("2018-05-18T04:00:00Z"), "Person" : ObjectId("5dcb6409e63830b7aa54fd6e") }, { "CompletedHours" : 32, "DateCompleted" : ISODate("2018-05-18T04:00:00Z"), "Person" : ObjectId("5dcb6409e63830b7aa54fd6e") } ] } ], "RecordID" : 9018, "RecordType" : "Item", "Status" : "Done" }
{ "ItemReport" : [ { "WorkDoneBy" : [ { "CompletedHours" : 1.5, "DateCompleted" : ISODate("2017-09-01T04:00:00Z"), "Person" : ObjectId("5dcb6409e63830b7aa54fe5f") } ] } ], "RecordID" : 9019, "RecordType" : "Item", "Status" : "Done" }
{ "ItemReport" : [ { "WorkDoneBy" : [ { "CompletedHours" : 2, "DateCompleted" : ISODate("2017-09-08T04:00:00Z"), "Person" : ObjectId("5dcb6409e63830b7aa54fd6e") }, { "CompletedHours" : 18, "DateCompleted" : ISODate("2017-09-15T04:00:00Z"), "Person" : ObjectId("5dcb6409e63830b7aa54fd6e") }, { "CompletedHours" : 7, "DateCompleted" : ISODate("2017-09-20T04:00:00Z"), "Person" : ObjectId("5dcb6409e63830b7aa54fd6e") } ] } ], "RecordID" : 9017, "RecordType" : "Item", "Status" : "Done" }

这里的问题是WorkDoneBy是一个嵌套在另一个数组中的数组 (ItemReport)。因此单身$filter还不够,因为您需要迭代两次。你可以加$map https://docs.mongodb.com/manual/reference/operator/aggregation/map/index.html迭代外部数组:

db.records.aggregate([
    {
        "$project": {
            "ItemReport": {
                $map: {
                    input: "$ItemReport",
                    as: "ir",
                    in: {
                        WorkDoneBy: {
                            $filter: {
                                input: "$$ir.WorkDoneBy",
                                as: "value",
                                cond: {
                                    "$and": [
                                        { "$ne": [ "$$value.DateCompleted", null ] },
                                        { "$gt": [ "$$value.DateCompleted", new Date("2017-01-01T12:00:00.000Z") ] },
                                        { "$lt": [ "$$value.DateCompleted", new Date("2018-12-31T12:00:00.000Z") ] }
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        }
    }
])
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MongoDB Mongoose 按日期范围查询深层嵌套的子文档数组 的相关文章

  • 如何在 Ubuntu VirtualBox 中运行 Meteor 应用程序并使用 Windows 主机上的编辑器进行编辑?

    我希望在运行 Ubuntu 的 virtualbox 来宾中运行一个用于开发目的的流星服务器 该项目将位于主机上的一个文件夹内 该文件夹将共享给来宾 该文件夹本身位于 Dropbox 文件夹内 这样我可以在多个虚拟机和工作站之间共享开发 但
  • express-hbs 实例 registerAsyncHelper 奇怪的哈希值

    我正在使用express hbs nodejs模块 但在使用时遇到问题registerAsyncHelper 我需要在限制范围内编译布局 因为我创建了一个新的 Handlebars 实例 并在该实例中创建了一个助手 但是当我编译布局时 它返
  • Nodejs 调试生产中的错误

    我有一个在生产环境中运行的 Nodejs 脚本 我不太可能 千分之一 遇到这样的错误 TypeError value is out of bounds at checkInt buffer js 1009 11 at Buffer writ
  • 如何获取nodejs程序中的nodejs版本?

    In a Node js 的调试器 https github com rocky trepanjs 有一个命令显示V8版本和调试器包版本 如何获取nodejs版本 我想我基本上可以运行命令node version or nodejs ver
  • 呃!尝试将包发布到 npm 时出现 403

    我正在尝试将包发布到 npm 您可以在此处查看存储库 https github com biowaffeln mdx state https github com biowaffeln mdx state 我登录到 npmnpm login
  • Jwt 签名和前端登录身份验证

    我有这个特殊的 jwt sign 函数 Backend const token jwt sign id user id process env TOKEN SECRET expiresIn 1m res header auth token
  • HTML 格式的 Google Apps 脚本

    是否可以在我的 HTML 中使用 google apps 脚本 我希望能够从外部框架 例如 Node js 以纯 Javascript 形式从表单写入电子表格 https developers google com apps script
  • 沙箱中的 Nodejs

    我使用 NodeJS 作为客户端浏览器和服务器之间的中间人来处理所有请求 我正在尝试使用 nodejs 作为过滤工具并突出显示 如果不是 所有恶意脚本 但我意识到nodejs让脚本以当前环境权限运行 因此 我决定通过安装沙箱在新的上下文中运
  • Bot Framework Node.js 发送给特定用户的临时消息

    我已经盯着这个问题好几个小时了 找不到解决方案 即使根据所有建议 它应该很容易 https learn microsoft com en us bot framework nodejs bot builder nodejs proactiv
  • 如何在Electron WebView中连接到代理?

    因为我可以通过连接到免费代理服务器 或付费 目前用作电子 JS 解决方案作为桌面应用程序 代理列表服务器示例 http proxylist hidemyass com http proxylist hidemyass com 您可以使用 s
  • 在最新的 MongoDB java 驱动程序中使用 createIndex() 时,索引已存在并出现不同选项错误

    所以我将 MongoDB java 驱动程序升级到 2 12 4 其中ensureIndex 方法已被弃用 我改为使用createIndex 从文档来看 该方法的功能类似于ensureIndex 但是 当我在生产中使用此方法时 出现以下错误
  • 如何在Windows服务器上将node.js文件作为后台进程运行?

    我正在创建一个 node js 项目并将其上传到我的 Windows 服务器 以为移动应用程序提供 API 服务 当我打开命令提示符并键入 node app js 它运行正常 但是当我关闭命令提示符时 我的 Node js 服务器停止运行
  • 缺少节点-v59-linux-x64/grpc_node.node

    我正在尝试在我的服务器中使用 Firebase admin SDK 当我部署时 出现错误 我在 firebase admin node module 映射中缺少文件 node v59 linux x64 grpc node node 我在包
  • Node.js 重写 toString

    我试图覆盖我的对象的默认 toString 方法 这是代码和问题 function test this code 0 later on I will set these this name test prototype toString f
  • editMessageReplyMarkup 方法删除内联键盘

    我正在使用 node js 制作一个电报机器人node telegram bot api图书馆 我回答callback query并想更换我的内联键盘 下面的代码显示了我如何尝试使用此方法 但是当我在电报中点击键盘时 它就消失了 bot o
  • Sequelize - 使用 es6 和模块运行迁移

    我不确定我是否做错了什么或者什么 我觉得我正在运行一个现代的 相当常见的堆栈 但我无法让新的 Sequelize v6 与我的设置完美配合 我在 Node v14 17 Sequelize v6 6 2 上 在我的 package json
  • NestJS e2e 测试模拟会话装饰器

    我正在尝试使用 supertest 编写一个 e2e 测试 其中我的控制器实际上使用了 Session 装饰师 然而 我不想承担使用数据库连接等启动会话的全部负担 因此测试中的我的应用程序实际上并未初始化会话 相反 我想首先模拟掉装饰器提供
  • 找不到“节点”的类型定义文件

    更新 Angular Webpack 和 TypeScript 后出现奇怪的错误 知道我可能会错过什么吗 当我使用 npm start 运行应用程序时 出现以下错误 at loader Cannot find type definition
  • 如何在超级测试中模拟中间件?

    我想测试中间件是否在app js叫做 虽然我嘲笑该模块work js 它仍然运行原始代码 app js const work require work const express require require const app expr
  • 我可以将 MongoDB 与实体框架一起使用吗?

    实体框架有可能支持MongoDB数据库吗 有人写过实体框架MongoDB Provider吗 简短的回答 不 这肯定是可能的 但不合理 MongoDB 是文档数据库 不支持集合之间的任何物理关系 EF 非常适合 SQL MySQL 等关系数

随机推荐