比较 MongoDB 中的两个日期字段
Posted
技术标签:
【中文标题】比较 MongoDB 中的两个日期字段【英文标题】:Compare two date fields in MongoDB 【发布时间】:2013-08-09 03:07:51 【问题描述】:在我的收藏中,每个文档都有 2 个日期,已修改和同步。我想找到那些修改过的>同步,或者同步不存在。
我试过了
'modified': $gt : 'sync'
但它没有显示我的预期。有什么想法吗?
谢谢
【问题讨论】:
【参考方案1】:您不能将一个字段与另一个字段的值进行正常查询匹配。但是,您可以使用聚合框架来做到这一点:
db.so.aggregate( [
$match: …your normal other query… ,
$match: $eq: [ '$modified', '$sync' ]
] );
我把……你正常的其他查询……放在那里,因为你可以让那个位使用索引。因此,如果您只想对 name
字段为 charles
的文档执行此操作,您可以这样做:
db.so.ensureIndex( name: 1 );
db.so.aggregate( [
$match: name: 'charles' ,
$project:
modified: 1,
sync: 1,
name: 1,
eq: $cond: [ $gt: [ '$modified', '$sync' ] , 1, 0 ]
,
$match: eq: 1
] );
输入:
"_id" : ObjectId("520276459bf0f0f3a6e4589c"), "modified" : 73845345, "sync" : 73234
"_id" : ObjectId("5202764f9bf0f0f3a6e4589d"), "modified" : 4, "sync" : 4
"_id" : ObjectId("5202765b9bf0f0f3a6e4589e"), "modified" : 4, "sync" : 4, "name" : "charles"
"_id" : ObjectId("5202765e9bf0f0f3a6e4589f"), "modified" : 4, "sync" : 45, "name" : "charles"
"_id" : ObjectId("520276949bf0f0f3a6e458a1"), "modified" : 46, "sync" : 45, "name" : "charles"
这会返回:
"result" : [
"_id" : ObjectId("520276949bf0f0f3a6e458a1"),
"modified" : 46,
"sync" : 45,
"name" : "charles",
"eq" : 1
],
"ok" : 1
如果您需要更多字段,您需要将它们添加到$project
。
【讨论】:
您确实应该避免使用$where
变体,因为它通过 javascript。另外,请接受答案。【参考方案2】:
对于 MongoDB 3.6 及更高版本:
$expr
运算符允许在查询语言中使用聚合表达式,因此您可以执行以下操作:
db.test.find( "$expr": "$gt": ["$modified", "$sync"] )
或使用带有$match
管道的聚合框架
db.test.aggregate([
"$match": "$expr": "$gt": ["$modified", "$sync"]
])
对于 MongoDB 3.0+:
您还可以将聚合框架与 $redact
管道运算符一起使用,它允许您使用 $cond
运算符处理逻辑条件并使用特殊操作$$KEEP
“保留”逻辑条件为真的文档或$$PRUNE
“删除”条件为假的文档。
考虑运行以下展示上述概念的聚合操作:
db.test.aggregate([
"$redact":
"$cond": [
"$gt": ["$modified", "$sync"] ,
"$$KEEP",
"$$PRUNE"
]
])
此操作类似于具有 $project
管道,该管道选择集合中的字段并创建一个新字段来保存逻辑条件查询的结果,然后是后续 @ 987654328@,除了 $redact
使用更高效的单个流水线阶段:
【讨论】:
【参考方案3】:简单
db.collection.find($where:"this.modified>this.sync")
例子
Kobkrits-MacBook-Pro-2:~ kobkrit$ mongo
MongoDB shell version: 3.2.3
connecting to: test
> db.time.insert(d1:new Date(), d2: new Date(new Date().getTime()+10000))
WriteResult( "nInserted" : 1 )
> db.time.find()
"_id" : ObjectId("577a619493653ac93093883f"), "d1" : ISODate("2016-07-04T13:16:04.167Z"), "d2" : ISODate("2016-07-04T13:16:14.167Z")
> db.time.find($where:"this.d1<this.d2")
"_id" : ObjectId("577a619493653ac93093883f"), "d1" : ISODate("2016-07-04T13:16:04.167Z"), "d2" : ISODate("2016-07-04T13:16:14.167Z")
> db.time.find($where:"this.d1>this.d2")
> db.time.find($where:"this.d1==this.d2")
>
【讨论】:
【参考方案4】:使用 Javascript,使用 foreach 并将 Date 转换为 toDateString()
db.ledgers.find().forEach(function(item)
if(item.fromdate.toDateString() == item.todate.toDateString())
printjson(item)
)
【讨论】:
【参考方案5】:现在您的查询正在尝试返回所有结果,使得modified
字段大于单词'sync'
。尝试去掉 sync
周围的引号,看看是否能解决任何问题。否则,我做了一些研究,发现this question。您尝试做的事情可能无法在单个查询中完成,但是一旦您从数据库中提取所有内容,您应该能够操作您的数据。
【讨论】:
谢谢@gr3co,我试图避免聚合,但似乎是唯一的出路...... :(【参考方案6】:要在不聚合的情况下解决此问题,请将您的查询更改为:
'modified': $gt : ISODate(this.sync)
【讨论】:
以上是关于比较 MongoDB 中的两个日期字段的主要内容,如果未能解决你的问题,请参考以下文章
转换以字符串格式存储的日期值并减去 mongodb 中的当前日期