mongoose中嵌入子文档数组的过滤

mongoose中嵌入子文档数组的过滤,mongoose,subdocument,Mongoose,Subdocument,我的主模式是一个事件,在数组中嵌入了一些步骤。我想查询事件,并过滤带有某些条件的步骤。因此,事件返回时并没有包含所有步骤,只包含与条件匹配的步骤。 我可以使用聚合来完成,但是我需要作为mongoose文档返回的文档,这样我就可以对每个文档使用save()函数,所以我想只能使用mongoose来完成 示例事件: { "_id" : ObjectId("5d57b6ad754e9d1ec0c123e6"), "title" : "wedding", "user" : ObjectId("

我的主模式是一个事件,在数组中嵌入了一些步骤。我想查询事件,并过滤带有某些条件的步骤。因此,事件返回时并没有包含所有步骤,只包含与条件匹配的步骤。 我可以使用聚合来完成,但是我需要作为mongoose文档返回的文档,这样我就可以对每个文档使用save()函数,所以我想只能使用mongoose来完成

示例事件:

{
  "_id" : ObjectId("5d57b6ad754e9d1ec0c123e6"),
  "title" : "wedding",
  "user" : ObjectId("5d4fedfd63dc55207cf128ff"),
  "date" : ISODate("2019-09-24T20:00:00.000Z"),
  "steps" : [
  {
    "_id" : ObjectId("5d57b6ad754e9d1ec0c123e7"),
    "title" : "home",
    "startDate" : ISODate("2019-06-27T20:00:00.000Z"),
    "endDate" : ISODate("2019-07-21T20:00:00.000Z"),
    "isDone" : false,
    "state" : 2
  },
  {
    "_id" : ObjectId("5d57b6ad754e9d1ec0c123e8"),
    "title" : "guests",
    "startDate" : ISODate("2019-07-07T20:00:00.000Z"),
    "endDate" : ISODate("2019-07-30T20:00:00.000Z"),
    "isDone" : false,
    "state" : 2
  },
  {
    "_id" : ObjectId("5d57b6ad754e9d1ec0c123e9"),
    "title" : "car",
    "startDate" : ISODate("2019-07-11T20:00:00.000Z"),
    "endDate" : ISODate("2019-07-20T20:00:00.000Z"),
    "isDone" : false,
    "state" : 2
  }
]
};
到目前为止,我的汇总如下:

const now = new Date();
Event.aggregate([
    {
      $match: { date: { $gte: now } },
    },
    {
      $unwind: '$steps',
    },
    {
      $match: { 'steps.startDate': { $lte: now }, 'steps.endDate': { $gte: now }, 'steps.state': { $ne: 1 } },
    },
  ])

我已经搜索了文档,但没有找到任何内容。

对于基于主文档和子文档中某些关键信息的更新子文档:

  var now = new Date()
  Events.find({
       date: { $gte: now }, 'steps.startDate': { $lte: now }, 'steps.endDate': { $gte: now }, 'steps.state': { $ne: 1 } 
    },
    (err, events) => {
        events.forEach(event => {
            var steps = event.steps.filter(step => (step.startDate < now && step.endDate > now && step.state != 1));
            steps.forEach(step => {step.state = 1;})
            event.save((err, event_)=>{console.log('event updated: ', event_)})
        })
    }
  )
var now=新日期()
Events.find({
日期:{$gte:now},'steps.startDate':{$lte:now},'steps.endDate':{$gte:now},'steps.state':{$ne:1}
},
(错误,事件)=>{
events.forEach(event=>{
var steps=event.steps.filter(step=>(step.startDatenow&&step.state!=1));
steps.forEach(step=>{step.state=1;})
event.save((err,event_)=>{console.log('event updated:',event_)})
})
}
)
我在其中测试的完整示例项目(它不是活动的):


(帮助:您应该运行此代码2次,第一次将
init
设置为true,以创建一些示例数据。第二次,将
init
设置为false,以运行实际查询。然后您可以在mongodb中检查数据库数据,以验证结果。)

是否要“查找这些事件的某些步骤满足条件的事件”或“查找事件并仅查找符合条件的事件的步骤”…我的意思是,您可以根据步骤条件查找事件,然后手动筛选该事件的事件(通过javascript
Array.filter
)。是这样吗?类似这样的情况:(首先获取符合临界条件的事件,然后再次筛选其事件。)@yayapro“查找事件并仅查找满足条件的事件的步骤”就是这种情况。问题在于性能,我无法获取所有事件,然后循环遍历所有事件。你弄错了。我没有说获取所有事件。我说的是“先获取匹配的事件,然后过滤它们的步骤”“我需要根据开始和结束日期更新每个步骤的状态。我正在使用创建cron作业的议程在午夜更新状态。因此,它基本上会搜索每个尚未通过日期的事件,并相应地更新步骤状态。这会导致与条件匹配的事件数量很大。谢谢您的回答。这和我现在正在做的差不多,但随着数据库的不断扩大,这将影响性能。这就是为什么我试图至少用一个查询来完成它。@ArootinAghazaryan没问题。阿格里说,这不是明智的表现。解决方法是在1个查询中删除该事件(通过其ID并使用
$in
),然后在1个查询中使用
insertMany
再次插入它们。因此,只需要两个查询。但实际上我不知道更好的方法。@ArootinAghazaryan您在问题
中也提到过,所以我可以对每个
使用save()函数,所以我假设您可以处理多个查询(请注意,像
events.forEach
event.steps.filter
steps.forEach
这样的东西在
ram
中执行,它们不是查询(而mongoose查询运行在文件系统上,速度要慢得多))(假设您的数据库有10个匹配事件,这个答案首先有1个查询来查找它们,然后有10个查询来保存它们。所以应该是11个)