MongoDB集合中的文档具有以下模式(仅显示相关字段):
{
"TTLinSeconds" : 1800,
"lastUpdatedTimestamp" : ISODate("...")
}
我需要删除current timestamp
大于lastUpdatedTimestamp
的所有文档以及TTLinSeconds
字段中存储的值。提前感谢您的建议。
答案 0 :(得分:5)
这可能有用(删除2017-01-25T00:30:00Z和2017-01-26T23:59:00Z之间的字段):
{{1}}
建议:
我建议您对变量使用通用命名约定。
参考:
https://docs.mongodb.com/manual/reference/operator/update/currentDate/
答案 1 :(得分:2)
您可以使用$where执行此操作:
db.collectionName.remove({$where:"new Date().getTime() > this.lastUpdatedTimestamp.getTime() + (this.TTLinSeconds * 1000)"})
答案 2 :(得分:1)
您可以将聚合框架与 $redact
和 $out
管道一起使用,以删除满足给定条件的文档。
$redact
管道包含 $project
和 $match
的功能,以实现字段级别编辑将使用$$KEEP
返回与条件匹配的所有文档,并使用 $$PRUNE
变量删除那些不匹配的文档。
$out
管道将聚合管道的结果文档写入同一个集合,从而基本上执行更新操作。
运行以下聚合操作将删除文档:
db.collection.aggregate([
{
"$redact": {
"$cond": [
{
"$lte": [
new Date(),
{
"$add": [
"$lastUpdatedTimestamp",
{ "$multiply": ["$TTLinSeconds", 1000] }
]
}
]
},
"$$KEEP",
"$$PRUNE"
]
}
},
{ "$out": "collection" }
])
需要注意的是,使用 $where
运算符的效果不会很好,因为MongoDB在幕后执行的操作需要一段时间才能处理查询:正常(非 $where
)查询,您的客户端将该查询转换为BSON并将其发送到数据库。 MongoDB也将数据存储在BSON中,因此它基本上可以将您的查询直接与数据进行比较。这非常快速有效。
另一方面,如果您的 $where
子句必须作为查询的一部分执行,那么MongoDB必须为集合中的每个文档创建一个JavaScript对象,解析文档'BSON并将其所有字段添加到JavaScript对象。然后它会执行您针对文档发送的JavaScript,然后再次将其全部删除。这是一个非常耗费时间和资源的操作,因为它调用JavaScript引擎来评估每个文档上的Javascript代码并检查每个文档的条件。如果可以的话,建议与索引查询结合使用,以便查询可以更快。
使用 considerations 时,您需要注意一些$where
:
不要使用全局变量。
$where
评估JavaScript并且无法利用索引。 因此,在表达查询时,查询性能会提高 使用标准的MongoDB运算符(例如,$gt
,$in
)。一般来说,你 只有当您无法使用其他人表达您的查询时,才应使用$where
运营商。如果您必须使用$where
,请尝试至少包含一个 标准查询运算符,用于过滤结果集。仅使用$where
需要表扫描。使用普通的非$where
查询语句 提供以下性能优势:MongoDB将在
$where
之前评估查询的非$where
组件 声明。如果非$where
语句不匹配任何文档,则MongoDB 不会使用$where
执行任何查询评估。非$where
查询语句可以使用索引。
$where
在必要时是一个很好的黑客,但应尽可能避免。如果需要 $where
查询,您可以通过最大限度地减少使用 $where
的文档数量来降低效果。创建一个额外的计算非规范化字段,说expiryDate
,它是lastUpdatedTimestamp
和TTLinSeconds
字段的总和,然后您可以将其查询为:
db.collection.remove({ "expiryDate": { "$lt": new Date() }});
但是,如果集合非常大,这样的低选择性字段不会产生良好的索引性能,因此使用这种方法索引的候选集很大。