【问题标题】:Mongo - Treat null or undefined fieled as a specific valueMongo - 将 null 或 undefined 字段视为特定值
【发布时间】:2015-12-26 21:59:10
【问题描述】:

我有以下情况:

考虑一个包含以下文档的集合:

 [
   {
      '_id': ObjectId('somehting'),
      'date': null
   },
   {
      '_id': ObjectId('somehting'),
   },
   {
      '_id': ObjectId('somehting'),
      'date': '2015-01-01 12:12:12'
   },
   many others
 ]

现在我有以下查询,可以查找日期介于值之间的文档 db.getCollection('validation_archive').find({'date': {$lte: '[date_here]', {$gte: '[date_here ]'}}});

一切正常,除了具有 null 或不存在的字段。

无论如何我可以告诉 mongo 将 null 视为 '0000-00-00 00:00:00' 吗?

编辑:我需要这样做,所以如果 $gt 中发送的日期是 0000-00-00 00:00:00,则查询将返回结果中的文档。

【问题讨论】:

    标签: mongodb mongodb-query


    【解决方案1】:

    在一般查询中则没有。您始终可以将它们从结果中排除,如下所示:

    db.getCollection('validation_archive').find({
        "date": { "$lte": date_to, "$gte" date_from, "$ne": null }
    })
    

    或者您可以使用 .aggregate() 建议的“零”或“纪元”日期来“包容”:

    db.getCollection('validation_archive').aggregate([
        { "$redact": {
            "$cond": {
                "if": {
                    "$and": [
                        { "$gte": [ date_from, { "$ifNull": [ "$date", new Date(0) ] } ] },
                        { "$lte": [ date_to, { "$ifNull": [ "$date", new Date(0) ] } ] }
                    ]
                },
                "then": "$$KEEP",
                "else": "$$PRUNE"
            }
        }}
    ])
    

    但是在你所问的上下文中,那么我们将不得不问“有什么意义”。

    或者即使你必须:

    db.getCollection('validation_archive').aggregate([
        { "$project": {
            "date": { "$ifNull": [ "$date", new Date(0) ] }
        }},
        { "$match": {
            "$or": [
                { "date": { "$lte": date_to, "$gte" date_from } }, 
                { "date": { "$eq": Date(0) } }
            ]
        }}
    ])
    

    这完全包含在结果中。

    但是又为什么不直接做:

    db.getCollection('validation_archive').find({
       "$or": [
            { "date": { "$lte": date_to, "$gte" date_from },
            { "date": null },
            { "date": { "$exists": false } }
       ]
    })
    

    这样效率更高。

    因此可以将不存在的日期“投影”为日期,但主要是简单地使用基本查询操作来代替。

    【讨论】:

    • 我不想从结果中排除它们,如果 $gt/$gte 参数是 '00-00-00' ,我想将它们包含在结果中。默认情况下它们被排除在外。编辑问题以反映这一点。
    • @zozo 例如,您需要考虑一下,因为“00-00-00”不在“2015-01-01”和“2015-12-01”的范围内。这就是为什么我说“重点是什么”。如果需要,您可以随时$project 并通过.aggregate() 添加$or 条件。
    • @zozo 甚至为你添加了一个例子。
    • db.getCollection('validation_archive').find({ "$or": [ { "date": { "$lte": date_to, "$gte" date_from }, { "date" : null }, { "date": { "$exists": false } } ] }) 这几乎是我需要的,但我需要添加 {'date': null} 和 {'date': {$exists : false}} 部分仅当 date_from 为 '0000-00-00 00:00:00' 时。我可以通过添加另一个 $and 和一个 $or 来做到这一点,但是查询变得非常“复杂”。这就是为什么我问您是否可以将 null 视为指定值(就像在 sql 中一样)。我想你不能:)。所以...赞成+接受。
    • @zozo 你错了,但接受是正确的做法,直到你意识到我是对的。
    【解决方案2】:

    如果要排除 date 等于 null 或不存在的结果,则

    db.getCollection('validation_archive').find({
      date: {
        $ne: null,
        $lt: '[date_here]',
        $gt: '[date_here]'
      }
    });
    

    【讨论】:

      【解决方案3】:
      1. 尝试在插入时将日期值设为 0。它将帮助您执行查询。
      2. 如果集合已经存在,您可以使用更新查询来更新日期字段。
      3. 使用 mongo 的投影技术插入一个新字段,例如 newDate,其值为 0 或实际日期。之后对 newDate 字段使用过滤器查询。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-16
        • 1970-01-01
        • 2021-10-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-30
        相关资源
        最近更新 更多