通过日期和数字字段的总和与当前时间戳之间的日期比较来删除文档

时间:2017-02-06 04:23:21

标签: mongodb mongodb-query mongo-shell

MongoDB集合中的文档具有以下模式(仅显示相关字段):

{
    "TTLinSeconds" : 1800,
    "lastUpdatedTimestamp" : ISODate("...")
}

我需要删除current timestamp大于lastUpdatedTimestamp的所有文档以及TTLinSeconds字段中存储的值。提前感谢您的建议。

3 个答案:

答案 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,它是lastUpdatedTimestampTTLinSeconds字段的总和,然后您可以将其查询为:

db.collection.remove({ "expiryDate": { "$lt": new Date() }});

但是,如果集合非常大,这样的低选择性字段不会产生良好的索引性能,因此使用这种方法索引的候选集很大。