【问题标题】:Get MongoDB documents where all subdocuments match criteria获取所有子文档都符合条件的 MongoDB 文档
【发布时间】:2017-04-24 21:20:12
【问题描述】:

我是Mongo 新手,所以这可能是一个微不足道的问题。请多多包涵:)

我的Mongo 文档可以按逻辑分组为有效归档 文档。文档有效,如果其revisions.validTo 日期字段中的任何null 或大于今天。否则,文档在存档中。

所以集合结构大致是:

[
    {
        _id: 'valid-1',
        info: 'This is valid document because it has a revision with null validTo value',
        revisions: [
            {
                validTo: ISODate("2014-01-01T00:00:00.000Z")
            },
            {
                validTo: null
            }
        ]
    },
    {
        _id: 'valid-2',
        info: 'This is valid document because it has a revision with validTo value > today',
        revisions: [
            {
                validTo: ISODate("2014-01-01T00:00:00.000Z")
            },
            {
                validTo: ISODate("2050-01-01T00:00:00.000Z")
            }
        ]
    },
    {
        _id: 'archive-1',
        info: 'This document is in archive as all revisions have validTo < today',
        revisions: [
            {
                validTo: ISODate("2014-01-01T00:00:00.000Z")
            }
        ]
    }
]

我可以很容易地查询到有效的文档

db.getCollection('collection').find({
  $or: [
    { 'revisions.validTo': { $gte: new Date() } },
    { 'revisions.validTo': null }
  ]
})

它返回[valid-1, valid-2],但我不知道如何查询归档文档以获得结果[archive-1]。例如

db.getCollection('collection').find({
  'revisions.validTo': { $lte: new Date() }
})

返回一个文档,如果它有任何带有validTo all 的revisions.validTo

由于集合恰好分为这两组,我可能还可以通过查询有效组然后获取整个集合和有效文档集之间的差异来获取存档组。这也许可以通过 Mongo 聚合框架来完成,但我还不知道如何做到这一点。

因此,热烈欢迎任何有关构建存档文档查询的帮助!

(我也在使用 Mongoose,如果这有帮助的话..?)

【问题讨论】:

  • 您的 validTo 应该是 ISO 日期。你的预期结果是什么?
  • 我编辑了示例集合以使用ISODates。还添加了有关预期输出的更多解释。

标签: mongodb mongoose mongodb-query


【解决方案1】:

您首先需要重新建模您的文档,以便日期为 ISODates,以便您可以查询对它们的操作

[
    {
        info: 'This is valid document because it has a revision with null validTo value',
        revisions: [
            {
                validTo: ISODate("2014-01-01T00:00:00.000Z")
            },
            {
                validTo: null
            }
        ]
    },
    {
        info: 'This document is in archive as all revisions have validTo < today',
        revisions: [
            {
                validTo: ISODate("2014-01-01T00:00:00.000Z")
            }
        ]
    }
]

那么你可以使用下面的查询:

db.docs.find({ 'revisions.validTo': { $lte: new Date() }, 'revisions.validTo': { $ne: null } } ).pretty()

返回

{
        "_id" : ObjectId("584a9a9212767a1fecf0e39f"),
        "info" : "This document is in archive as all revisions have validTo < today",
        "revisions" : [
                {
                        "validTo" : ISODate("2014-01-01T00:00:00Z")
                }
        ]
}

【讨论】:

  • 感谢您的回复!不幸的是,这种方法似乎不起作用。如果我理解正确,当多次使用相同的对象键 (revisions.validTo) 时,实际上只使用了最后一个条件。所以应该要么使用$and: [...],要么使用隐含的$andrevisions.validTo: { $ne: null, $not: { $gt: new Date() } }
【解决方案2】:

您可以尝试使用$and$not$ne 运算符,如下所示,

db.getCollection('collection').find({
  $and: [
    { 'revisions.validTo': { $lte: new Date() } },
    { 'revisions.validTo': { $not: { $gte: new Date() } } },
    { 'revisions.validTo': { $ne: null } }
  ]
})

【讨论】:

  • 哇,成功了!实际上,似乎甚至不需要$lte 标准。诀窍是声明没有revisions.validTo 可以大于今天。我不敢相信我花了多长时间才明白这一点。谢谢!!
猜你喜欢
  • 1970-01-01
  • 2020-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-29
  • 2017-12-09
  • 2021-05-24
  • 1970-01-01
相关资源
最近更新 更多