Dear,
I'am trying to count value in my mongo db but the aggregation return empty array.
My query look like this:
Order.aggregate(
[
{
'$match': {
createdAt : {
'$gte' : new Date("2017-11-29").setHours(14,43,0,0),
'$lt' : new Date()
}
}
},
{
$group: {
_id: null,
count: {
$sum: 1
}
}
}
]
).exec().then(r => {
console.log(r); // []
});
An other (and dirty) query works fine:
Order.find({
createdAt : {
'$gte' : new Date("2017-11-29").setHours(14,43,0,0),
'$lt' : new Date()
}
}).exec().then(orders => {
console.log(orders.length);// 1463
})
Did I miss something?
Thanks in advance
why not
Order.count({
createdAt : {
'$gte' : new Date("2017-11-29").setHours(14,43,0,0),
'$lt' : new Date()
}
}).exec().then(count=> {
console.log(count);// 1463
})
Related
I have a mongoDB collection which I use with a mongoose Schema :
const balanceSchema = new mongoose.Schema({
userId: {
type: mongoose.Schema.Types.ObjectId, ref: 'user'
},
incomes: { Number },
fees: { Number },
},
{ strict: false })
I use the strict mode to false, so I can push any 'key' I want with its value.
I would like to delete just one of the "incomes" category, but I can't specify the line because there is no 'defined key'.
Here is an exemple of the data inside :
{
"_id": {
"$oid": "60c763df3d260204865d2069"
},
"incomes": {
"income1": 1300,
"anyKeyNameIWant": 400
},
"fees": {
"charge1": 29,
"charge2": 29,
"chargetest": 29,
"charge7": 29
},
"__v": 0,
}
I tried this, but no success :
module.exports.deleteOneBalance = (req, res) => {
let data = req.body
if (!ObjectID.isValid(req.params.id))
return res.status(400).send('ID unknown : ' + req.params.id);
BalanceModel.update(
{ _id: req.params.id },
{
$unset: { "incomes.salairetest": "400" }
}), (err, docs) => {
if (!err) res.send('Deleted. ' + data)
else console.log('Error : ' + err)
}
}
Any idea ?
There are several ways to delete fields with dynamic field names.
One solution is this one:
var unset = {};
unset["incomes." + "anyKeyNameIWant"] = null;
db.balanceModel.updateOne({ _id: req.params.id }, { $unset: unset })
Or you can use an aggregation pipelinie like this:
db.balanceModel.updateOne(
{ _id: req.params.id },
[
{ $set: { incomes: { $objectToArray: "$incomes" } } },
{ $set: { incomes: { $filter: { input: "$incomes", cond: { $ne: ["$$this.k", "anyKeyNameIWant"] } } } } },
{ $set: { incomes: { $arrayToObject: "$incomes" } } }
]
)
If you want to remove/unset specific value/(s) from the documents then you have to provide the complete path of that key.
Let's take an example if you want to remove anyKeyNameIWant then your path will be incomes.anyKeyNameIWant and the update query will be like this
db.sample.update(
{
_id: ObjectId("60c763df3d260204865d2069")},
{
$unset: {"incomes.anyKeyNameIWant":""}
})
In your code, you are passing an object having the key incomes in $unset which will remove the complete incomes key from the document
Here is the link to the official document in case you want more details $unset
I have an nested data structure like this:
{
"_id" : ObjectId("5f51362883fc9424bcc3ed76"),
"count" : [
{
"page" : "SHOE",
"visit_count" : 2,
"guestip" : [
{
"ip" : "192.168.1.4",
"visit" : 1
},
{
"ip" : "192.168.1.5",
"visit" : 1
}
]
},
{
"page" : "TSHIRTS",
"visit_count" : 2,
"guestip" : [
{
"ip" : "192.168.1.1",
"visit" : 1
},
{
"ip" : "192.168.1.2",
"visit" : 1
}
]
}
],
"createdate" : ISODate("2020-09-03T18:30:00.056Z"),
"__v" : 0
}
How I can increment the visit counter for 192.168.1.2 ip ib TSHIRTS section.
What I tried:
I am using node.js and mongoose;
const isIPExists = (ip, arr) => arr.some(el => String(el.ip) === ip);
//NOTE: Below code is under async function that is why used the await.
const data = await CollectionName.findOne(
{ createdate: { $gte: finaldate } },
{ assetpage_visit_count: { $elemMatch: { page: req.body.page } } },
).exec();
if (data.count.length === 0) {
//This part works fine
await CollectionName.updateOne(
{ createdate: { $gte: finaldate } },
{
$push: {
count: {
page: req.body.page, //Here let's say TSHIRTS is sending
visit_count: 1,
guestip: [
{
ip: req.body.ip,
visit: 1
}
]
},
},
).exec();
} else {
const storeIpArray = data.count[0].guestip;
let xfilter = {
$inc: {
'count.$.visit_count': 1,
},
$push: {
'count.$.guestip': {
ip: req.body.ip,
visit: 1
}
}
}
if (isIPExists(req.body.ip, storeIpArray) === true) {
xfilter = {
$inc: {
'count.$.visit_count': 1,
'count.$.visit_count.$.visit': 1
},
}
}
await CollectionName.updateOne(
{
createdate: { $gte: finaldate },
'count.page': req.body.page,
},
xfilter,
).exec();
}
return res.send("Done")
}
Any help or suggestion is really appreciated for the increment count under nested structure. Pardon for the indenting as code was very long so just split the issue part here and mentioned the code manually.
Use arrayFilters.
This exactly query is very well explain in the documentation Update Nested Arrays in Conjunction with $[] with copy-pasteable examples.
You just had to update field names to match your documents:
db.CollectionName.update(
{},
{ $inc: { "count.$[p].guestip.$[ip].visit": 1 } },
{ arrayFilters: [
{ "p.page": "TSHIRTS" } ,
{ "ip.ip": "192.168.1.2" }
] })
Please note, the subdocument with source ip "192.168.1.2" must be in the array for $inc to increment it, so you may need to push it with visit:0 before running the update query.
I want to update multiple documents.
My current Document,
Document Account
{
"_id" : "5cbd96aca1a6363473d4g8745",
"contact" : [
"5cbd96aca1a6363473d4a968",
]
},
{
"_id" : "5cbd96aca1a6363473d4g8746",
"contact" : [
"5cbd96aca1a6363473d4z7632",
]
}
I need below output,
update contact array with different _id.
Document Account
{
"_id" : "5cbd96aca1a6363473d4g8745",
"contact" : [
"5c98833f98770728a7047f1a",
"5cbd96aca1a6363473d4a968",
]
},
{
"_id" : "5cbd96aca1a6363473d4g8746",
"contact" : [
"5caddf78b8c0645402090536",
"5cbd96aca1a6363473d4z763",
]
}
Use $addToSet or $push to push id with bulk update.
You can use update with upsert. It will update the doc if exist and if not then it will create new one.
for example:
//Make a obj to set
var contacts = {
id: req.body.id,
contactIds: req.body.contactIds,
};
req.app.db.models.ModelsName.update(
{
//if you want multiple fields to be update
$and: [{ id: contacts.id }, { contactIds: { $in: contacts.contactIds } }]
},
//Set the above obj
{ $set: contacts },
{ upsert: true },
(err, result) => {
if (err) {
console.log(err.message)
}
console.log("Updated successfully")
})
This is just a reference. Modify accordingly your use.
You can use Bulk.find.update() method to update all matching documents.
example:
var bulk = db.items.initializeUnorderedBulkOp();
bulk.find( { status: "D" } ).update( { $set: { status: "I", points: "0" } } );
bulk.find( { item: null } ).update( { $set: { item: "TBD" } } );
bulk.execute();
Here is my code
Bill.aggregate(
{$unwind:'$detais'},
{ $match : {
createdOn : {
$gt : moment().startOf('day'),
$lt : moment().endOf('day')
}
}
},
{
$group : {
_id : '$detais.product_id',
total : { $sum : '$detais.quantity' },
}
},
{ $sort :{ total: -1 } }
)
.limit(10)
.exec((err, records) => {
if (err) {console.log(err)};
res.send({
data : records
});
});
The query
createdOn : {
$gt : moment().startOf('day'),
$lt : moment().endOf('day')
}
work fine in another case.
But in aggregate is empty result... Please someone tell me where i'm mistake....
You need to apply $and condition in $match.
Bill.aggregate({
$unwind: '$detais'
}, {
$match: {
createdOn: {
$and: [{
$gt: moment().startOf('day')
},
{
$lt: moment().endOf('day')
}]
}
});
This question already has answers here:
Moongoose aggregate $match does not match id's
(5 answers)
Closed 6 years ago.
Stack:
+ Mongoose 4.4.10 (last stable version) already tested with older versions
+ MongoDb 2.6.3
I execute that function in mongodb console, with successfully re
db.activities.aggregate(
{ $match : { 'organizer': ObjectId("5408e4609640de8768c1d212") } }
, { $group :
{ _id : "$organizer",
totalSwims: { $sum : 1 },
longestSwim : { $max: "$distance" },
moreDistanceSwim : { $max: "$duration" },
warmestWaterSwim : { $max: "$activityWeather.waterTemperature" },
coldestWaterSwim : { $min: "$activityWeather.waterTemperature" },
warmestSwim : { $max: "$activityWeather.temperature" },
coldestSwim : { $min: "$activityWeather.temperature" }}});
{ "_id" : ObjectId("5408e4609640de8768c1d212"), "totalSwims" : 50, "longestSwim" : 6512.997, "moreDistanceSwim" : "02:35", "warmestWaterSwim" : "22", "coldestWaterSwim" : "22", "warmestSwim" : "15", "coldestSwim" : "15" }
But If I try through mongoose is returning always an empty array [] I already have some aggregate functions working well, but don't know why that one is not working.
activities.aggregate([
{ $match : { 'organizer': userId } },
{ $group : {
_id : "$organizer",
totalSwims: { $sum : 1 },
longestSwim : { $max: "$distance" },
moreDistanceSwim : { $max: "$duration" },
warmestWaterSwim : { $max: "$activityWeather.waterTemperature" },
coldestWaterSwim : { $min: "$activityWeather.waterTemperature" },
warmestSwim : { $max: "$activityWeather.temperature" },
coldestSwim : { $min: "$activityWeather.temperature" }
} } ]
, function(err, result){
if (err) {
console.error('Problem %s', err);
return next(err);
} else {
console.error('Result %j', result);
return next(null, result);
}
});
Any idea?
Thank you
Sorry, after searching for a while before posting without any relevant result I finally figured it out. It seams that, just for that case, I need to ensure the id with the ObjectId method instead to send just an string.
var ObjectID = require("mongodb").ObjectID;
activities.aggregate([
{ $match : { 'organizer': ObjectID(userId) } },