【问题标题】:Mongo messy DOB string field to AgeMongo凌乱的DOB字符串字段到年龄
【发布时间】:2021-05-18 03:51:35
【问题描述】:

我有一个包含以下文档的集合:

{'state': 'NY', 'DOB': '2000-01-02'},
{'state': 'NY', 'DOB': '2002/03/04'},
{'state': 'NY', 'DOB': '00-00-00'},
{'state': 'NY', 'DOB': 'male'},
...

我想要这样的输出:

{'state': 'NY', 'DOB': '2000-01-02', 'Age': 21},
{'state': 'NY', 'DOB': '2002/03/04', 'Age': 19},
{'state': 'NY', 'DOB': '00-00-00', 'Age': None}, # or Mongo None equivalent
{'state': 'NY', 'DOB': 'male', 'Age': None}, # or Mongo None equivalent
...

我正在 PyMongo 中构建聚合查询,我想知道是否有一种聚合方式可以尝试将字段转换为 Mongo Date 对象,然后从中提取Age,否则(如果无法提取日期) ,返回无。下面的shell中的一些条件?

def map_age(state, city)
    db.aggregate([
        {'$match': {
             'state': state,
             'DOB': {"$exists": True}, 
             'Age': {"$exists": False}
        }},
        {...}     
    ])

【问题讨论】:

  • 为什么不在你的代码中做呢?
  • 您可以使用$dateFromString聚合运算符。

标签: python mongodb aggregation-framework pymongo


【解决方案1】:

你可以试试,

  • $let为dob转换创建变量并进行操作
  • $dateFromString 从字符串转换为日期,如果有效,则替换为“无”
  • $subtract 从当前日期减去转换后的日期 $$NOW 您也可以使用 new Date()
  • $divide 上面的“31536000000”减去日期意味着“3652460601000”
  • $round 对年龄进行四舍五入
db.aggregate([
  {
    $set: {
      Age: {
        $let: {
          vars: {
            dob: {
              $dateFromString: {
                dateString: "$DOB",
                onError: "None"
              }
            }
          },
          in: {
            $cond: [
              { $eq: ["$$dob", "None"] },
              "None",
              {
                $round: {
                  $divide: [
                    { $subtract: ["$$NOW", "$$dob"] },
                    31536000000 // 365*24*60*60*1000
                  ]
                }
              }
            ]
          }
        }
      }
    }
  }
])

Playground

【讨论】:

  • 我不确定这会产生预期的结果......例如,返回标准化值,如 0.0
  • 很好的答案。与仅使用 $dateFromString 相比,结合使用 $let 操作会对性能产生什么影响?只是好奇。提前致谢。
  • 性能会影响任何聚合运算符,而不仅仅是$let,因此有一个 mongodb 经验法则,您可以添加更多字段,或者使用您的数据库中的重复数据可以需要的格式,但不要为格式化查询结果做更多​​的操作......为了处理罕见的情况,我们可以使用这些聚合运算符......
  • @turivishal 毕竟这行得通——你知道如何实现它以便它真正更新集合中的所有文档吗?
  • @turivishal 没关系,已解决,谢谢!
【解决方案2】:

按照@prasad_ 的建议,您必须在$project$addFields 阶段使用$dateFromString 运算符。

db.collection.aggregate([
  {
    "$project": {
      "age": {
        "$dateFromString": {
          dateString: "$DOB",
          onError: null,
          onNull: null,
        }
      }
    }
  }
])

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-09
相关资源
最近更新 更多