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

Delete documents by date comparison between sum of date and numeric fields and current timestamp

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

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

我需要删除 current timestamp 大于 lastUpdatedTimestamp 加上存储在 TTLinSeconds 字段中的值的所有文档。预先感谢您的建议。

这可能有效(删除 2017-01-25T00:30:00Z 和 2017-01-26T23:59:00Z 之间的字段):

  db.collectionName.remove({
       $and : [
        {"lastUpdatedTimestamp": { 
           $gte:   ISODate("2017-01-25T00:30:00Z"), 
           $lt :   ISODate("2017-01-26T23:59:00Z")
       },
       {"TTLinSeconds" : value}
      ]
    }  

建议:

我建议您对变量使用通用命名约定。

参考:

https://docs.mongodb.com/manual/reference/operator/update/currentDate/

您可以使用 $where 作为:

db.collectionName.remove({$where:"new Date().getTime() > this.lastUpdatedTimestamp.getTime() + (this.TTLinSeconds * 1000)"})

您可以使用带有 $redact and $out 管道的聚合框架来删除满足给定条件的文档。

$redact pipeline incorporates the functionality of $project and $match to implement field level redaction where it will return all documents matching the condition using $$KEEP and removes those that don't match using the $$PRUNE变量。

$out管道将聚合管道的结果文档写入同一个集合,因此本质上是在执行更新操作。


运行 以下聚合操作将删除文档:

db.collection.aggregate([
    {
        "$redact": {
            "$cond": [
                { 
                    "$lte": [ 
                        new Date(), 
                        { 
                            "$add": [
                                "$lastUpdatedTimestamp", 
                                { "$multiply": ["$TTLinSeconds", 1000] }
                            ] 
                        } 
                    ] 
                },
                "$$KEEP",
                "$$PRUNE"
            ]
        }
    },
    { "$out": "collection" }
])

作为警告,使用 $where operator won't perform very well as it takes a while to process the query because of what MongoDB is doing behind the scenes: when you perform a normal (non-$where) 查询,您的客户端将该查询转换为 BSON 并将其发送到数据库。 MongoDB 也将数据存储在 BSON 中,因此它基本上可以直接将您的查询与数据进行比较。这是非常快速和有效的。

另一方面,当您有一个必须作为查询的一部分执行的 $where 子句时,MongoDB 将不得不创建一个JavaScript 集合中每个文档的对象,解析文档的 BSON 并将它们的所有字段添加到 JavaScript 对象。然后它执行您针对文档发送的 JavaScript ,然后再次将其全部删除。这是一个非常耗时和 resource-intensive 的操作,因为它调用 JavaScript 引擎来评估每个文档上的 Javascript 代码并检查每个文档的条件。如果可以,建议结合索引查询,这样查询可能会更快。

使用$where:

的一些注意事项

Do not use global variables.

$where evaluates JavaScript and cannot take advantage of indexes. Therefore, query performance improves when you express your query using the standard MongoDB operators (e.g., $gt, $in). In general, you should use $where only when you can’t express your query using another operator. If you must use $where, try to include at least one other standard query operator to filter the result set. Using $where alone requires a table scan. Using normal non-$where query statements provides the following performance advantages:

MongoDB will evaluate non-$where components of query before $where statements. If the non-$where statements match no documents, MongoDB will not perform any query evaluation using $where. The non-$where query statements may use an index.

$where 在必要时是一个很好的技巧,但应尽可能避免。如果需要 $where 查询,您可以通过最小化进入 $where 的文档数量来降低性能损失 或创建一个额外的计算非规范化字段,比如 expiryDate,它是 lastUpdatedTimestampTTLinSeconds 字段的总和,然后您可以将其查询为:

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

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