MongoDB populate items before $pull condition - mongodb

Users collection:
[
{
_id: '5b3935c2d4850aa2d9f0ae25',
feedBucket: ['5b37d16665c4127e7a088812', '5b3a19c5be4949b0d74476d4']
},
{
_id: '35c2d4850aa2d9f0ae25ab39',
feedBucket: ['5b37d16665c4127e7a088812', '5b3a19c5be4949b0d74476d4']
}
]
Post collection:
[
{
_id: '5b37d16665c4127e7a088812',
createdAt: 2018-07-01 23:12:50.232
},
{
_id: '5b3a19c5be4949b0d74476d4',
createdAt: 2018-05-01 23:12:50.232
},
]
I want to execute following:
const date = new Date()
date.setMonth(date.getMonth() - 1)
await User.updateMany(
{},
{ $pull: { feedBucket: { createdAt: { $lte: date } } } }
)
Is there any way to populate feedBucket items before $pull condition?
Or feedBucket shouldn't be an array of items ids, but should be an array of item documents?

You can try the code below:
const postsToPull = await Post.find({ createdAt: { $lte: date } });
await User.updateMany(
{},
{ $pull: { feedBucket: { $in: postsToPull } }
)
Another option is to store createdAt within feedBicket like
{
_id: ObjectId,
createdAt: Date
}
Then you can query it with
await User.updateMany(
{},
{ $pull: { feedBucket: { createdAt: { $lte: date } } } }
)

Related

MongoDB: Group by date and other value

I have this values on my MongoDB:
I need to group them by date and by the value. I need to create a chart that shows when the value changed. And I need to show only if the value changed.
How can I do it in MongoDb?
My currently aggregation is like this:
let history = await History.aggregate([
{
$match: {
address: "123456",
token_to_index: "1"
}
},
{
$group: {
_id : {
date: "$date",
floor_price: "$stats.floor_price"
},
count: { $sum: 1 }
}
},
{
$sort: { "_id.date": 1}
}
]);
I basically need this on MongoDB:
history = history.filter((item, index) => {
if(index === 0) {
return item;
} else {
if(history[index-1]._id.floor_price !== item._id.floor_price) {
return item;
}
}
})
Thanks!
You can change your query,
$group by floor_price field and get max date by $max
$sort by date in ascending order
let history = await History.aggregate([
{
$match: {
address: "123456",
token_to_index: "1"
}
},
{
$group: {
_id: "$stats.floor_price",
date: { $max: "$date" },
count: { $sum: 1 }
}
},
{ $sort: { "date": 1 } }
])
Playground

mongodb $pull in array with another array

Help me please to remove elements in an array with such document schema:
contracts: [
{
bandwidth: {
calculated: {
value: Number,
documents: [id1, id2, id3, id4],
}
}
}
]
I want to delete elements in all documents array that are in filter array.
I tried:
const documentsToDelete = [id2, id3]
const points = await Point.updateMany({
$pull: {
contracts: {"bandwidth.calculated.documents": {$in: documentsToDelete}}
},
});
But it does not work. The resulting array must contain "id1" and "id4"
Correct the things,
the first parameter is the query part to match the condition
the contracts is an array so use $[] to update operation in all elements
const documentsToDelete = [id2, id3];
const points = await Point.updateMany(
{},
{
$pull: {
"contracts.$[].bandwidth.calculated.documents": {
$in: documentsToDelete
}
}
}
)
Playground
bellow quires worked for me well
let feed = await Feed.findOneAndUpdate(
{
_id: req.params.id,
feeds: {
$elemMatch: {
type: FeedType.Post,
locations: {
$elemMatch: {
uniqueName,
},
},
},
},
},
{
$pull: {
//#ts-ignore
'feeds.$[].locations': { uniqueName },
},
},
{ new: true }
);
or
let feed = await Feed.findOneAndUpdate(
{
$and: [
{
_id: req.params.id,
},
{
'feeds.$[].locations': {
$elemMatch: {
uniqueName,
},
},
},
],
},
{
$pull: {
//#ts-ignore
'feeds.$[].locations': { uniqueName },
},
},
{ new: true }
);

Mongo: $match returns an empty array when is added to aggregate

I have a query like this:
const data = await this.iveModel
.aggregate([
{
$group: {
_id: { $month: '$createdAt' },
count: { $sum: 1 },
},
},
])
.exec();
It works fine, but I want to limit the result to the current year, so I have added this:
const inicioDeAnio = moment()
.startOf('year')
.toISOString();
const finDeAnio = moment()
.endOf('year')
.toISOString();
const num = await this.iveModel
.aggregate([
{
$match: {
createdAt: {
$gt: inicioDeAnio,
$lt: finDeAnio
}
}
},
{
$group: {
_id: { $month: '$createdAt' },
count: { $sum: 1 },
},
},
])
.exec();
And this always returns an empty array.
I do not know what I'm doing wrong.
Your inicioDeAnio and finDeAnio variable is just string, if you want to query by date, you need to use ISODate. Something like:
...{
$match: {
createdAt: {
$gt: ISODate(inicioDeAnio),
$lt: ISODate(finDeAnio)
}
}...

mongodb - how to project last element of an array after an update

So I have the following query:
ListModel
.findOneAndUpdate(
{
_id: list_id
},
{
$push: {
"items": {
details: the_template
}
}
},
{
new: true,
projection: {
items: 1
}
}
)
So, this returns me the array of the updated document, but how would I get only the last element inserted?
You can use of $slice, in your case :
ListModel
.findOneAndUpdate(
{
_id: list_id,
},
{
$push: {
items: {
details: the_template,
},
},
},
{
new: true,
projection: {
items: {
$slice: -1,
},
},
},
);

MongoDB $pull from array with filter

I have User collection:
[
{
_id: '5b3935c2d4850aa2d9f0ae25',
feedBucket: [
{
_id: '2a3535c2d4852ba2d9f0ae52',
createdAt: '2018-06-30 21:52:22.681'
},
{
_id: '9f342c2d4852ba2d9f0ae52',
createdAt: '2018-06-30 21:52:22.681'
}
]
},
{
_id: '3d2343c2d4850aa2d9f0ae33',
feedBucket: [
{
_id: '2a3535c2d4852ba2d9f0ae52',
createdAt: '2018-02-30 21:52:22.681'
},
{
_id: '9f342c2d4852ba2d9f0ae52',
createdAt: '2018-06-30 21:52:22.681'
}
]
}
]
And I am trying to pull document with id - '9f342c2d4852ba2d9f0ae52' from users feedBucket.
await User.updateMany(
{},
{ $pull: { feedBucket: { _id: '9f342c2d4852ba2d9f0ae52' } } },
{ multi: true }
)
but it doesn't work, result is { n: 2, nModified: 0, ok: 1 }
If your feedBucket._id is ObjectId then you need to $pull it by converting to mongoose ObjectId
const user = await User.update(
{ },
{ $pull: { feedBucket: { _id: mongoose.Types.ObjectId('5b07fa836569d356ba5bd2fa') } } },
{ multi: true }
)