.project({
percentage_amount: {
$multiply: ["$commission", {
$divide: ["$price", 100]
}]
},
payable: {
$subtract: ["$price", percentage_amount]
}
})
Is this possible in mongoose? if not, how to do that? kindly help me out
Yes it's possible with the aggregation framework. You can either use the aggregate() pipeline builder as:
Model.aggregate()
.project({
"percentage_amount": {
"$multiply": [
"$commission", {
"$divide": ["$price", 100]
}
]
},
"payable": {
"$subtract": ["$price", percentage_amount]
}
})
.exec(function(err, result) {
if (err) return handleError(err);
console.log(result)
});
or using the aggregate() operator pipeline array:
Model.aggregate([
{
"project": {
"percentage_amount": {
"$multiply": [
"$commission", {
"$divide": ["$price", 100]
}
]
},
"payable": {
"$subtract": ["$price", percentage_amount]
}
}
]).exec(function(err, result) {
if (err) return handleError(err);
console.log(result)
});
Related
The below aggregation is working in mongo db, but when i tried to integrate this with node js to get the count value through API, its returned null value
I am currently finding out ways to do Aggregation in Node js.
Below are the integration code with node js
app.get('/count', (req, res) => {
var name = req.params.name;
adpostdata.aggregate([
{ "$facet": {
"Total": [
{ "$match" : { "category": { "$exists": true }}},
{ "$count": "Total" },
]
}},
{ "$project": {
"Total": { "$arrayElemAt": ["$Total.Total", 0] },
}}
], (err, result) => {
if (err) return console.log(err)
console.log(result)
res.send(result+"")
})
})
my input is
{
category :"dress"
}
{
category:"cars"
}
Thanks all of you for your help, now i am able to get my excepted outputs
app.get('/count', (req, res) => {
adpostdata.aggregate(
[
// Count the number of books published in a given year
{
$facet: {
"categories": [
{
$group: {
_id: '$category',
count: { $sum: 1 }
}
},
// Sort by year descending
{ $sort: { count: -1, _id: -1 } }
],
"Total": [
{ "$match" : { "category": { "$exists": true }}},
{ "$count": "Total" },
],
}}]).toArray( (err, result) => {
if (err) return console.log(err)
console.log(result)
res.send(result)
})
})
I have a output like this but i wanna filter events array by _id's which is same with parent object _id.I wanna filter it according to this condition.
[
{
"_id": "5cc45eb430aaba3cdc045dc0" ,
"word": "Pasta",
"translate": "Makarna",
"kind": "İsim",
"exampleSentence": "asljdalsd",
"__v": 0,
"events": [
{
"_id": "5cc45eb430aaba3cdc045dc0",
"createdAt": "2019-04-27T13:52:15.721Z",
"TenMinutesLater": "2019-04-27T13:52:25.721Z",
"OneWeekLater": "2019-05-04T13:52:15.721Z",
"OneMonthLater": "2019-05-27T13:52:15.721Z",
"FourMonthLater": "2019-08-27T13:52:15.721Z",
"__v": 0
},
{
"_id": "5cc45ee630aaba3cdc045dc1",
"createdAt": "2019-04-27T13:52:15.721Z",
"TenMinutesLater": "2019-04-27T13:52:25.721Z",
"OneWeekLater": "2019-05-04T13:52:15.721Z",
"OneMonthLater": "2019-05-27T13:52:15.721Z",
"FourMonthLater": "2019-08-27T13:52:15.721Z",
"__v": 0
}
]
}
]
I wanna filter my events array which is have same _id property with parent object _id.How should be my query acording to what I want ?
this is my query
Word.find({ _id: req.params.id }, (err, words) => {
if (err) {
console.log(err);
}
const uid = words.map(word => word._id);
console.log(req.params.id);
Word.aggregate([
{
$match: {
_id: {
$in: uid.map(function(id) {
return new mongoose.Types.ObjectId(id);
})
}
}
},
{
$lookup: {
from: "tests",
localField: "eventId",
foreignField: "_id.str",
as: "events"
}
}
])
.then(data => {
res.json(data);
})
.catch(err => {
throw err;
});
});
I want the output like this.How I filter it with parent object's _id ?
[
{
"_id": "5cc45eb430aaba3cdc045dc0" ,
"word": "Pasta",
"translate": "Makarna",
"kind": "İsim",
"exampleSentence": "asljdalsd",
"__v": 0,
"events": [
{
"_id": "5cc45eb430aaba3cdc045dc0",
"createdAt": "2019-04-27T13:52:15.721Z",
"TenMinutesLater": "2019-04-27T13:52:25.721Z",
"OneWeekLater": "2019-05-04T13:52:15.721Z",
"OneMonthLater": "2019-05-27T13:52:15.721Z",
"FourMonthLater": "2019-08-27T13:52:15.721Z",
"__v": 0
]
}
]
Here $lookup will return all the events that matches localfield/foreign field condition as you might already know. If you want to filter results by some other criteria (which is not very clear from your description) you can use pipeline feature in joined collection (introduced in 3.6). A sample pipeline in $lookup (take from official site) would look like this. So as you can see you can execute match on joined collection and filter your events.
db.orders.aggregate([
{
$lookup:
{
from: "warehous`enter code here`es",
let: { order_item: "$item", order_qty: "$ordered" },
pipeline: [
{ $match:
{ $expr:
{ $and:
[
{ $eq: [ "$stock_item", "$$order_item" ] },
{ $gte: [ "$instock", "$$order_qty" ] }
]
}
}
},
{ $project: { stock_item: 0, _id: 0 } }
],
as: "stockdata"
}
}
])
Thanks answer but I finally solved the problem like this.it is working perfectly
Word.find({ _id: req.params.id }, (err, words) => {
if (err) {
console.log(err);
}
const uid = words.map(word => word._id);
Word.aggregate([
{
$match: {
_id: {
$in: uid.map(function(id) {
return mongoose.Types.ObjectId(id);
})
}
}
},
{
$lookup: {
from: "tests",
localField: "_id.str",
foreignField: "eventId",
as: "events"
}
},
{
$addFields: {
events: {
$filter: {
input: "$events",
as: "event",
cond: {
$eq: ["$$event._id", mongoose.Types.ObjectId(req.params.id)]
}
}
}
}
}
])
.then(data => {
res.json(data);
})
.catch(err => {
throw err;
});
});
How can I get the result from mongoose aggregation and display it with ejs?
This is my code:
Record.aggregate(
[
{
$group:
{
_id: { month: { $month: "$date"}, year: { $year: "$date"} },
totalExpense: { $sum: "$amountExpense"},
totalIncome: { $sum: "$amountIncome"},
count: { $sum: 1 }
}
},
{ "$project": {
"total": { "$subtract": [ "$totalIncome", "$totalExpense" ] }
}},
{
$out: "total"
}
]), function(err, results) {
console.log(results);
res.json(results);
}
I simply want to count the element in array based on the query. I tried the following command but not solved my problem.
I want to count the element whose TimeStamp is in between "2017-02-17T18:30:00.000Z and "2017-02-18T18:29:59.999Z" on DATA2 array, but it returns only 1.
CODE Executed:
CODE 1
db.ABC.aggregate([{
$match: {
$and: [{
DATA2: {
$exists: true
}
}, {
"DATA2.TimeStamp": {
$gte: require('../../modules/getDates').getFromDate(item),
$lte: require('../../modules/getDates').getToDate(item)
}
}, {
Client_id: "123" /*req.query.client_id*/
}]
}
}, {
$project: {
DATASiz: {
$size: "$DATA2"
},
"has bananas": {
$in: ["DATA2.$.TimeStamp"]
}
}
}], function(err, result) {
console.log(result)
callBack();
})
Code 2
db.abc.find({ $and:[{DATA2: {$exists: true}},{Client_id: "123"},{"DATA2": { $elemMatch: { TimeStamp: { $gte: require('../../modules/getDates').getFromDate(item), $lte: require('../../modules/getDates').getToDate(item) } } }}]
}, function(err, result) {
console.log(JSON.stringify(result))
callBack();
})
Code 3
//db.abc.find //also tried
db.abc.count({
$and: [{
DATA2: {
$exists: true
}
}, {
"DATA2.TimeStamp": {
$gte: require('../../modules/getDates').getFromDate(item),
$lte: require('../../modules/getDates').getToDate(item)
}
}, {
Client_id: "123" /*req.query.client_id*/
}]
},{
"DATA2.$":1
}, function(err, result) {
console.log(result)
callBack();
})
JSON Format:
{
"_id": {
"$oid": "57c7404985737e2c78fde6b3"
},
"ABC": "1304258470",
"Status": "Not Found",
"DATA1": [
{123},{123},{123}
],
"Remark": "Not Found",
"DATA2": [
{
"TimeStamp": "2017-02-18T09:01:43.060Z",
"NdrStatus": "Door Locked",
},
{
"TimeStamp": "2017-02-18T08:09:43.347Z",
"NdrStatus": "HOLD",
},
{
"TimeStamp": "2017-02-20T08:09:43.347Z",
"NdrStatus": "HOLD",
}
]
}
Result:
I am getting the first element of DATA2 using CODE 3 but I know that as per the query 2 elements are to return.
I expect 2 as in count.
Also used $unwind $redact
Thanks in advance.
You can use the $filter and $size operators for this:
var start = require('../../modules/getDates').getFromDate(item),
end = require('../../modules/getDates').getToDate(item);
db.ABC.aggregate([
{
"$match": {
"DATA2": { "$exists": true },
"DATA2.TimeStamp": { "$gte": start, "$lte": end },
"Client_id": "123"
}
},
{
"$project": {
"DATASiz": {
"$size": {
"$filter": {
"input": "$DATA2",
"as": "item",
"cond": {
"$and": [
{ "$gte": ["$$item.TimeStamp", start] },
{ "$lte": ["$$item.TimeStamp", end] }
]
}
}
}
}
}
}
], function(err, result) {
console.log(result);
callBack();
});
I am trying to update two documents in mongoDB, with two different values. I made it with two different callbacks, but is it possible to do it with only one request?
My solution:
mongo.financeCollection.update(
{ 'reference': 10 },
{ $push:
{ history: history1 }
}, function (err){
if (err){
callback (err);
}
else {
mongo.financeCollection.update(
{ 'reference': 20 },
{ $push:
{ history: history2 }
}, function (err){
if (err){
callback(err);
}
else {
callback(null);
}
});
}
});
Sorry if it is a stupid question but I just want to optimize my code!
Best to do this update using the bulkWrite API. Consider the following example for the above two documents:
var bulkUpdateOps = [
{
"updateOne": {
"filter": { "reference": 10 },
"update": { "$push": { "history": history1 } }
}
},
{
"updateOne": {
"filter": { "reference": 20 },
"update": { "$push": { "history": history2 } }
}
}
];
mongo.financeCollection.bulkWrite(bulkUpdateOps,
{"ordered": true, "w": 1}, function(err, result) {
// do something with result
callback(err);
}
The {"ordered": true, "w": 1} ensures that the documents will be updated on the server serially, in the order provided and thus if an error occurs all remaining updates are aborted. The {"w": 1} option determines the write concern with 1 being a request acknowledgement that the write operation has propagated to the standalone mongod or the primary in a replica set.
For MongoDB >= 2.6 and <= 3.0, use the Bulk Opeartions API as follows:
var bulkUpdateOps = mongo.financeCollection.initializeOrderedBulkOp();
bulkUpdateOps
.find({ "reference": 10 })
.updateOne({
"$push": { "history": history1 }
});
bulkUpdateOps
.find({ "reference": 20 })
.updateOne({
"$push": { "history": history2 }
});
bulk.execute(function(err, result){
bulkUpdateOps = mongo.financeCollection.initializeOrderedBulkOp();
// do something with result
callback(err);
});