Mongodb aggregation does't work with $match between times - node.js

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')
}]
}
});

Related

MongoDB mongoose update elemMatch doesn't work but when query (find) it's ok

I'm having some problems on update using $elemMatch.
When I try to match or find, it shows the write result.
.updateOne(
{ _id: req.body.sid },
{ $pull: {comments: { $elemMatch: { fid: '5ea9c87d2d5c8f491cae8818' } }}}
).then((res)=>{
console.log(res)
}).catch((err)=>{
console.log(err)
})
It's resulting :
{ n: 1, nModified: 0, ok: 1 }
And it's the query result using find:
.find({
$and: [
{ _id: req.body.sid },
{comments: { $elemMatch: { fid: '5ea9c87d2d5c8f491cae8818' } }}
]
})
Sample doc result of find :
[
{
_id: 5ea88b12423e6e4b3ce01956,
comments: [{"fid":"5ea9c87d2d5c8f491cae8818","comment":"ok"}, {"fid":"5ea9c87d2d5c8f491cae8899","comment":"ok"}],
date: 2020-04-28T00:00:00.000Z,
title: 'Fotos para o Álbum de ensaios',
__v: 5
}
]
can anybody help me? Thank you!!
You can try like below :
If your documents look something like :
/* 1 */
{
"_id" : "5ea88b12423e6e4b3ce01956",
"comments" : [
{
"fid" : "5ea9c87d2d5c8f491cae8818"
},
{
"fid" : "5ea9c87d2d5c8f491cae8899"
}
],
"date" : "2020-04-28T00:00:00.000Z",
"title" : "Fotos para o Álbum de ensaios",
"__v" : 5.0
}
/* 2 */
{
"_id" : "5ea88b12423e6e4b3ce01951",
"comments" : [
{
"fid" : "5ea9c87d2d5c8f491cae8811"
},
{
"fid" : "5ea9c87d2d5c8f491cae8899"
}
],
"date" : "2020-04-28T00:00:00.000Z",
"title" : "Fotos para o Álbum de ensaios",
"__v" : 5.0
}
So $elemMatch is not needed on single query condition which in your case {comments: { $elemMatch: { fid: '5ea9c87d2d5c8f491cae8818' } }} can just be "comments.fid": "5ea9c87d2d5c8f491cae8818", also you don't need $and operator in your .find().
Query :
/** Here "comments.fid" helps to filter doc, even though we'll get single doc based on `_id` filter but
* still adding this check prevents unnecessary update operation if `5ea9c87d2d5c8f491cae8818` doesn't exists in fid of comments in doc */
.updateOne(
{ _id: req.body.sid, "comments.fid": "5ea9c87d2d5c8f491cae8818" },
{ $pull: { "comments" :{ "fid": "5ea9c87d2d5c8f491cae8818" } } }
)
.then((res) => {
console.log(res);
})
.catch((err) => {
console.log(err);
});

Aggregate date Range Mongoose

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
})

Mongoose Aggregation match an array of objectIds

I have a schema that Looks like this
var Post = new mongoose.Schema({
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
created: {
type: Date,
Default: Date.now
})
I have a User Table as well. I Have a array of user ids and i am trying to search the post table based on an array of user ids
For Example
var userIds = ["575e96652473d2ab0ac51c1e","575e96652473d2ab0ac51c1d"] .... and so on
I want to return all posts created by these users. And posts should be sorted by their creation date. Is there a way to group this post based on the user ids provided, basically match the posts for an individual user?
The result I am trying to attain is something like this:
[{
userAId : "56656.....",
post : [postA, postB],
},{
userBId :"12345...",
post : [postA, postB]
}]
How do I write this query?
This is what I have so far
Post.aggregate([{
// {"$unwind" : ""},
// "$group": {
// _id: "$author",
// "created" : {"$sum" : 1 }
// }
"$match" : { author : id}
}]).exec(function(error, data) {
if(error){
return console.log(error);
}else{
return console.log(data)
}
})
{
"_id" : ObjectId("575e95bc2473d2ab0ac51c1b"),
"lastMod" : ISODate("2016-06-13T11:15:08.950Z"),
"author" : ObjectId("575dac62ec13010678fe41cd"),
"created" : ISODate("2016-06-13T11:15:08.947Z"),
"type" : "photo",
"end" : null,
"commentCount" : 0,
"viewCount" : 0,
"likes" : 0,
"tags" : [],
"title" : "Today is a good day",
"__v" : 0
}
To return all posts created by users depicted in a list of ids, use the $in operator in your query and then chain the sort() method to the query to order the results by the created date field:
Post.find({ "author": { "$in": userIds } })
.sort("-created") // or .sort({ field: 'asc', created: -1 });
.exec(function (err, data){
if(err){
return console.log(err);
} else {
return console.log(data);
}
});
To get a result where you have the post id's grouped per user, you need to run the following aggregation operation:
Post.aggregate([
{ "$match" : { "author": { "$in": userIds } } },
{ "$sort": { "created": -1 } },
{
"$group" : {
"_id" : "$author",
"posts" : { "$push": "$_id" }
}
},
{
"$project": {
"_id": 0,
"userId": "$_id",
"posts": 1
}
}
]).exec(function (err, result){
if(err){
return console.log(err);
} else {
return console.log(result);
}
});
Or with the fluent API:
Post.aggregate()
.match({ "author": { "$in": userIds } })
.sort("-created")
.group({
"_id" : "$author",
"posts" : { "$push": "$_id" }
})
.project({
"_id" : 0,
"userId" : "$_id",
"posts": 1
})
.exec(function (err, result){
if(err){
return console.log(err);
} else {
return console.log(result);
}
});
This should be possible without aggregation.
Post
.find({ author: { $in: userIds } })
.sort({ created: -1 })
If you get CastError: Cast to ObjectId failed, make sure to map your userIds array from an array of strings to an array of mongoose id's.
userIds = userIds.map(userId => new mongoose.Types.ObjectId(userId))

Mongoose aggregate return empty result and working in mongo console [duplicate]

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) } },

How to build query for relating parent document's field to embedded array document's field. Using MongoDB aggregation Operators

Consider the following document in the collection named 'CityAssociation'
{
"_id" : "MY_ID",
"ThisCityID" : "001",
"CityIDs" : [{
"CityID" : "001",
"CityName" : "Bangalore"
}, {
"CityID" : "002",
"CityName" : "Mysore"
}],
"CityUserDetails": {
"User" : "ABCD"
}
}
Now I have User value i.e. in above case I have value ABCD and want to find it with only city where the first level's field ThisCityID matches to the embedded array documnet's field CityID. Finally I need to project as follows (for the above case):
{
'UserName': 'ABCD',
'HomeTown':'Bangalore'
}
In Node.js + MongoDB native drive, I wrote a aggregation query as follows which is not working as expected.
collection.aggregate([
{ $match: { 'CityUserDetails.User': 'ABCD', 'CityIDs': { $elemMatch: { CityID: ThisCityID}}} },
{ $unwind: "$CityIDs" },
{ $group: {
_id: '$_id',
CityUserDetails: { $first: "$CityUserDetails" },
CityIDs: { $first: "$CityIDs" }
}
},
{ $project: {
_id: 0,
"UserName": "$CityUserDetails.User",
"HomeTown": "$CityIDs.CityName"
}
}
], function (err, doc) {
if (err) return console.error(err);
console.dir(doc);
}
);
Can anyone tell me how this can be done with query.
Note: On MongoDB schema we don't have control to change it.
You can use the $eq operator to check if the first level's field ThisCityID matches embedded array document's field CityID.
db.city.aggregate([
{ $match : { "CityUserDetails.User" : "ABCD" }},
{ $unwind : "$CityIDs" },
{ $project : {
matches : { $eq: ["$CityIDs.CityID","$ThisCityID"]},
UserName : "$CityUserDetails.User",
HomeTown : "$CityIDs.CityName"
}},
{ $match : { matches : true }},
{ $project : {
_id : 0,
UserName : 1,
HomeTown : 1
}},
])
And the result is:
{
"result" : [
{
"UserName" : "ABCD",
"HomeTown" : "Bangalore"
}
],
"ok" : 1
}

Resources