如何通过具有最新日期的子文档上的条件查询文档

时间:2018-05-27 16:17:16

标签: javascript mongodb mongodb-query

我正在尝试根据最新子文档的条件找出查询文档的最佳方法。

所以我的数据可能如下所示:

[{
  _id: '59bb31efae69726bd5fc9391',
  name: 'Something',
  terms: [
    {
      _id: '58e54f5aad59a6000cdcd590',
      begDate: '2017-06-13T07:00:00.000Z',
      endDate: '2018-01-01T07:59:59.999Z'
    },
    {
      _id: '59bb32765e651d28909ed706',
      begDate: '2018-01-01T08:00:00.000Z',
      endDate: '2019-01-01T07:59:59.999Z'
    }
  ]
}, {
  _id: '59f20ddeef426f6bca3abbf1',
  name: 'Something',
  terms: [
    {
      _id: '59f20e35c8257b5b0f22d2a6',
      begDate: '2018-06-13T07:00:00.000Z',
      endDate: '2019-01-01T07:59:59.999Z'
    },
    {
      _id: '59f20e9394c8108d9db33bf9',
      begDate: '2019-01-01T08:00:00.000Z',
      endDate: '2020-01-01T07:59:59.999Z'
    }
  ]
}]

我想要的是获取 上一学期 endDate2019-01-01T07:59:59.999Z的所有文件{ _id: { '$in': [ ObjectId("591e5e37abddad14afe1b272"), ObjectId("591e5e37abddad14afe1b123") ] } } 这可以通过获取最后一个字词来完成一个数组,或者更可靠地排序术语,然后抓住最后一个。

我可以看到我如何用$where做到这一点,但我知道如果我能找到另一种更高效的方式。

我也想添加,无论我在这里做什么都会伴随其他查询参数。例如:

P5

更新

如上所述,这个问题有重复(我很难找到,因为引用的问题很难理解)。话虽这么说,我不仅在寻找阵列中的最后一个,而且也是最近的(我同意在问题正文中不清楚)。我不反对重复的问题参考,但是为了使未来的读者更容易,你会在接受的答案中找到mongo 3.6+的一个干净的解决方案,以及对评论中另一个问题的参考。如果您想在子文档中按日期查询 ,应该会有所帮助。

1 个答案:

答案 0 :(得分:1)

使用$expr执行“复杂”匹配,使用$let使用中间变量存储使用"$arrayElemAt": [ "$terms", -1 ]找到的数组的最后一个元素,以便将其与相关日期进行比较:

db.collection.find({
  $expr: {
    $let: {
      vars: { "last": { $arrayElemAt: [ "$terms", -1 ] } },
      in: { $eq: [ "$$last.endDate", "2019-01-01T07:59:59.999Z" ] }
    }
  } 
})

返回您提供第一条记录的输入。

并且,根据您的要求,为了不排除添加其他过滤器的可能性,您可以使用$and添加它们:

db.collection.find({
  $and: [
    { $expr: { $let: {
      vars: { "last": { $arrayElemAt: [ "$terms", -1 ] } },
      in: { $eq: [ "$$last.endDate", "2019-01-01T07:59:59.999Z" ] }
    }}},
    { "_id": { $ne: "sss" } } // actually whatever additional filter
  ]
})

如果您希望使用匹配的文档执行其他阶段,可以使用aggregate管道实现完全相同的事情:

db.collection.aggregate([
  { $match: {
    $and: [
      { $expr: { $let: {
        vars: { "last": { $arrayElemAt: [ "$terms", -1 ] } },
        in: { $eq: [ "$$last.endDate", "2019-01-01T07:59:59.999Z" ] } 
      }}},
      { "_id": { $ne: "sss" } }
    ]
  }},
  { ... }
])