Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/node.js/34.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
Node.js MongoDB Mongoose按日期范围查询深度嵌套的子文档数组_Node.js_Mongodb_Mongoose_Mongodb Query_Aggregation Framework - Fatal编程技术网

Node.js MongoDB Mongoose按日期范围查询深度嵌套的子文档数组

Node.js MongoDB Mongoose按日期范围查询深度嵌套的子文档数组,node.js,mongodb,mongoose,mongodb-query,aggregation-framework,Node.js,Mongodb,Mongoose,Mongodb Query,Aggregation Framework,我有一个问题,但并不完全相同,因为我的数据结构嵌套得更深,而公认的答案并没有解决这个问题 技术:MongoDB 3.6、Mongoose 5.5、NodeJS 12 我试图查询一个嵌套很深的对象数组。查询将接受用户提供的“开始日期”和“结束日期”。Item Report是一个子文档数组,其中包含另一个子文档数组“完成的工作”。所有在开始和结束日期范围内具有“CompletedDate”的WorkDoneBy对象都应与其他几个属性一起返回 所需的返回属性: let RecordsSchema =

我有一个问题,但并不完全相同,因为我的数据结构嵌套得更深,而公认的答案并没有解决这个问题

技术:MongoDB 3.6、Mongoose 5.5、NodeJS 12

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

所需的返回属性:

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
    }
  }],
});
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") ] }
                        ]
                    }
                }
            }
        }
    }
])
{ "_id" : ObjectId("5dcb6406e63830b7aa54269d"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa5426fb"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa542708"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa542712"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
RecordID、RecordType、Status、ItemReport.WorktoneBy.DateCompleted、ItemReport.WorktoneBy.CompletedHours、ItemReport.WorktoneBy.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
    }
  }],
});
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") ] }
                        ]
                    }
                }
            }
        }
    }
])
{ "_id" : ObjectId("5dcb6406e63830b7aa54269d"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa5426fb"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa542708"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa542712"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
尝试1:

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
    }
  }],
});
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") ] }
                        ]
                    }
                }
            }
        }
    }
])
{ "_id" : ObjectId("5dcb6406e63830b7aa54269d"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa5426fb"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa542708"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa542712"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
尝试1返回:

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
    }
  }],
});
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") ] }
                        ]
                    }
                }
            }
        }
    }
])
{ "_id" : ObjectId("5dcb6406e63830b7aa54269d"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa5426fb"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa542708"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa542712"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
所需回报(为简洁起见,已删除id):

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
    }
  }],
});
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") ] }
                        ]
                    }
                }
            }
        }
    }
])
{ "_id" : ObjectId("5dcb6406e63830b7aa54269d"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa5426fb"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa542708"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
{ "_id" : ObjectId("5dcb6406e63830b7aa542712"), "ItemReport" : [ { "WorkDoneBy" : [ ] } ] }
请注意,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
是不够的,因为您需要迭代两次。您可以添加以在外部数组上迭代:

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") ] }
                                    ]
                                }
                            }
                        }
                    }
                }
            }
        }
    }
])
请检查以下内容:

db.collection.aggregate([
{
$项目:{
_id:0,
记录编号:1,
记录类型:1,
现状:1,
项目报告:{
$let:{
变量:{
wdb:{
美元减少:{
输入:“$ItemReport.WorkDoneBy”,
初始值:[],
在:{
$concatarray:[
“$$this”,
“$$value”
]
}
}
}
},
在:{
工作人员:{
$filter:{
输入:“$$wdb”,
作为:“项目”,
条件:{
美元及:[
{
$gte:[
“$$item.DateCompleted”,
ISODate(“2010-01-10T04:00:00Z”)//开始日期
]
},
{
$lte:[
“$$item.DateCompleted”,
ISODate(“2018-01-10T04:00:00Z”)//结束日期
]
},
]
}
}
}
}
}
}
}
}
])

谢谢!有没有办法删除与查询不匹配的结果?例如,有几个结果与查询不匹配,但返回一个空的worktoneby数组<代码>{“_id”:“5dcb6406e63830b7aa5427f6”,“ItemReport”:[{“WorkDoneBy”:[]}},@pengz是的,只需使用$size筛选出那些具有空数组的。如果你需要一个例子,请告诉我(今天晚些时候我可以提供一个,现在没有时间),再次感谢!是的,举个例子会很有帮助。还有一种方法可以“填充”“个人”引用吗?我需要返回每个人的
DisplayName
属性。对于这些改进,我有一个单独的问题,如果你想获得另一个“公认答案”的分数: