Reputation:
I am attempting to delete all the documents returned by an aggregation in Mongodb.
The query I have is as follows:
db.getCollection("Collection")
.aggregate([
{
$match: { status: { $in: ["inserted", "done", "duplicated", "error"] } }
},
{
$project: {
yearMonthDay: { $dateToString: { format: "%Y-%m-%d", date: "$date" } }
}
},
{ $match: { yearMonthDay: { $eq: "2019-08-06" } } }
])
.forEach(function(doc) {
db.getCollection("Collection").remove({});
});
I tried this query but it removes all the data in the database, any suggestions please?
Upvotes: 17
Views: 30921
Reputation: 2598
You can add expires
to your document, and update this field in the $merge
stage of your aggregation.
// 1) add this to your schema
deleteAt: {
type: Date,
expires: 0,
}
// 2) set the value of `deleteAt` for the documents to be deleted
// 3) add this at the end of the aggregation
$merge: {
into: "Collections" // or "Collection"
}
Upvotes: 0
Reputation: 36104
As per your query its not required to filter by aggregation and remove by another methods, you can apply this query filters in remove() method's filters,
db.getCollection("Collection").remove({
$and: [
{ status: { $in: ["inserted", "done", "duplicated", "error"] } },
{
$expr: {
$eq: [
{ $dateToString: { format: "%Y-%m-%d", date: "$date" } },
"2019-08-06"
]
}
}
]
});
This can also support in deleteOne and deleteMany methods.
Upvotes: 5
Reputation: 3529
Since the remove doesn't have a query condition its going to match with all the documents and delete irrespective of the aggregation result.
Solution (match the ids of the current cursor doc):
db.getCollection("Collection")
.aggregate([
{
$match: { status: { $in: ["inserted", "done", "duplicated", "error"] } }
},
{
$project: {
yearMonthDay: { $dateToString: { format: "%Y-%m-%d", date: "$date" } }
}
},
{ $match: { yearMonthDay: { $eq: "2019-08-06" } } }
])
.forEach(function(doc) {
db.getCollection("Collection").remove({ "_id": doc._id });
});
Another better solution would be to have single round trip to db while deletion is get a list of ids from the aggregation cursor()
via cursor.map()
var idsList = db
.getCollection("Collection")
.aggregate([
{
$match: { status: { $in: ["inserted", "done", "duplicated", "error"] } }
},
{
$project: {
yearMonthDay: { $dateToString: { format: "%Y-%m-%d", date: "$date" } }
}
},
{ $match: { yearMonthDay: { $eq: "2019-08-06" } } }
])
.map(function(d) {
return d._id;
});
//now delete those documents via $in operator
db.getCollection("Collection").remove({ _id: { $in: idsList } });
Upvotes: 32