按日期和数字字段总和与当前时间戳之间的日期比较删除文档
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
,它是 lastUpdatedTimestamp
和 TTLinSeconds
字段的总和,然后您可以将其查询为:
db.collection.remove({ "expiryDate": { "$lt": new Date() }});
但是,如果集合非常大,这样的 low-selectivity 字段仍然不会产生良好的索引性能,因此使用这种方法索引的候选集很大。
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
,它是 lastUpdatedTimestamp
和 TTLinSeconds
字段的总和,然后您可以将其查询为:
db.collection.remove({ "expiryDate": { "$lt": new Date() }});
但是,如果集合非常大,这样的 low-selectivity 字段仍然不会产生良好的索引性能,因此使用这种方法索引的候选集很大。