I am new to mongoose, I am facing a problem while trying to fetch some data using aggregate query.
One part of my auction schema is:
"_id" : ObjectId("56c58be1faaa402c0d4ae66f"),
"auction_name" : "Auction2",
"auction_start_datetime" : ISODate("2016-02-18T09:30:00.000Z"),
"auction_end_datetime" : ISODate("2016-02-22T09:00:00.000Z"),
"auction_status" : "active",
"auction_series" : "GA-06-C",
"auction_reserve_price" : 1000,
"auction_increment_amount" : 200,
"fancy_numbers" : [
{
"number_end_datetime" : ISODate("2016-02-22T09:00:00.000Z"),
"number_start_datetime" : ISODate("2016-02-18T09:30:00.000Z"),
"increment_amount" : 200,
"reserve_price" : 1000,
"number" : 5000,
"_id" : ObjectId("56c58da3faaa402c0d4ae739"),
"bid_users" : [
{
"user_id" : "56c416a599ad7c9c1611b90b",
"bid_amount" : 7200,
"bid_time" : ISODate("2016-02-18T11:58:53.025Z"),
"user_name" : "amit#mailinator.com",
"_id" : ObjectId("56c5aec4acebf3b4061a645e")
},
{
"user_id" : "56c172dc302a2c90179c7fd1",
"bid_amount" : 15400,
"bid_time" : ISODate("2016-02-19T10:38:43.506Z"),
"user_name" : "rbidder#mailinator.com",
"_id" : ObjectId("56c5afe0d2baef7020ede1b6")
},
{
"user_id" : "56c477afb27a7ed824c54427",
"bid_amount" : 2800,
"bid_time" : ISODate("2016-02-18T11:56:58.830Z"),
"user_name" : "bidder2#mailinator.com",
"_id" : ObjectId("56c5b18a78c3fb340a8c6d75")
},
{
"user_id" : "56c5b17378c3fb340a8c6d73",
"bid_amount" : 5600,
"bid_time" : ISODate("2016-02-18T11:58:34.616Z"),
"user_name" : "bidder3#mailinator.com",
"_id" : ObjectId("56c5b1d778c3fb340a8c6d78")
}
]
}
]
Here, fancy_number is an array under auction collection and bid_users is an array under each fancy_number.
I have the user_id, I want to query and get only the bid_user records in which he is the highest bidder.
For example:
There are 3 users bidded 200,300,400 respectively, I want to get the
record (i.e number and amount) only if this particular user bid is 400
(highest). where ill be passing the user_id
The aggregate query which I wrote is:
var ObjectID = require('mongodb').ObjectID;
tempId = new ObjectID(req.body.aId);
auctionModel.aggregate({$match: {'_id': tempId}},
{$unwind: '$fancy_numbers'},
{$unwind:"$fancy_numbers.bid_users"},
{$group: {'_id':"$fancy_numbers.number" , maxBid: { $max: '$fancy_numbers.bid_users.bid_amount'}}},
function(err, bidData){
if(err){
console.log('Error :' + err);
}
else if(bidData) {
console.log(bidData);
}
});
Somehow this query is not working, its only giving records of max bid and number. I want records only if he is the highest bidder.
If I catch you correctly, please try to do it through $sort, and $limit to retrieve the highest bidder as below
auctionModel.aggregate(.aggregate([
{$match: {'_id': '123'}},
{$unwind: '$fancy_numbers'},
{$unwind: '$fancy_numbers.bid_users'},
{$sort: {bid_amount: 1}},
{$limit: 1}]);
Related
Unable to retrieve the list of previous one-year records from today Including null dates in node MongoDB from Contacts collection.
Sample Collection:
{
"_id" : ObjectId("5cb6a9ee8f145b97daf7181b"),
"Name" : "David",
"Age" : "25",
"JoiningDate" : 2019-06-01T06:18:22.359+00:00
}
{
"_id" : ObjectId("5cb3a9ee8f1d1b75daf7181b"),
"Name" : "Smith",
"Age" : "28",
"JoiningDate" : 2019-12-01T06:35:22.865+00:00
}
{
"_id" : ObjectId("5cb3r4ee8f1d1b75daf7181b"),
"Name" : "Peter",
"Age" : "23",
"JoiningDate" : null
}
{
"_id" : ObjectId("5cb4w7ee8f1d1b75daf7181b"),
"Name" : "Maria",
"Age" : "23"
}
{
"_id" : ObjectId("5cb9a9ee8f1d1b24daf7181b"),
"Name" : "Alicia",
"Age" : "24",
"JoiningDate" : 2018-06-01T06:18:22.109+00:00
}
My Code is:
var collection = db.collection('Contacts');
var fromDate = new Date(Date.now() - 365*24*60*60 * 1000);
var data = collection.find({ $or: [{"JoiningDate":{$gt: fromDate}}, {"JoiningDate":{$eq: ''}} ]} );
What wrong I am doing, please correct me!
As undefined,null and someval have different meanings, your query needs to cover all of these cases in order to retrieve all the data.
Use this query which utilises some basic boolean logic to achieve this:
db.getCollection('test').find(
{
$or: [
{"JoiningDate": {$gt: fromDate}},
{"JoiningDate": {$eq: null}},
{"JoiningDate": {$exists: false}}
]
})
I have 2 collections namely eventPart and Participants.
eventPart:{
{
"_id" : ObjectId("5b62676ba5419449046a26c4"),
"rollNo" : "15K21A0528",
"eventName" : "Ebullienza",
"team" : 68,
"__v" : 0
},{
"_id" : ObjectId("5b62676ba5419449046a26c5"),
"rollNo" : "15G11A0518",
"eventName" : "Ebullienza",
"team" : 68,
"__v" : 0}
}
Participants : {
{
"_id" : ObjectId("5b62626d9306a610e36aca95"),
"rollNo" : "15S11A0528",
"name" : "Pavan Boro",
"email" : "pavan#gmail.com",
"mobile" : NumberLong(6700332950),
"branch" : "CSE",
"section" : "A",
"year" : 4
}, {
"_id" : ObjectId("5b62633d9306a610e36acae1"),
"rollNo" : "15S11A0518",
"name" : "Manoj",
"email" : "manoj#gmail.com",
"mobile" : NumberLong(9700332910),
"branch" : "CSE",
"section" : "A",
"year" : 4
}}
I want to query the database with eventName in eventPart along with data in Participant collection.
Ex:
With eventName : 'Ebullienza'
I want to fetch all the details that is related to eventName: 'Ebullienza' in Participants collection.
I have tried collecting the rollNo from eventPart and using it for in Participants collection.
But I get stuck in collecting the rollNo in array
var rollNumber = new Array();
EventPart.find({'eventName':'Ebullineza'}).then(function(a){
a.forEach(function(roll){
rollNumber.push(roll.rollNo);
});
});
console.log(rollNumber); // prints [] - empty array
rollNumber is printed as [].
I think there could be a more efficient way of query 2 collections in mongoose.
Thanks.
use $lookup
db.eventPart.aggregate([
{ "$match": { "eventName": "Ebullienza" } },
{
"$lookup": {
"from": "Participants",
"localField": "rollNo",
"foreignField": "rollNo",
"as": "Participants"
}
}
])
print your array in the callback... otherwise he is printed before the end of execution of your find
var rollNumber = new Array();
EventPart.find({'eventName':'Ebullineza'}).then(function(a){
a.forEach(function(roll){
rollNumber.push(roll.rollNo);
});
console.log(rollNumber); // prints [] - empty array
});
I have a db Data as follows
{
"_id" : ObjectId("5a2109572222085be93ef10d"),
"name" : "data1",
"date" : "2017-12-01T00:00.0Z",
"status" : "COMPLETED"},{
"_id" : ObjectId("5a2109572222085be93ef10d"),
"name" : "data1",
"date" : "2017-12-01T00:00.0Z",
"status" : "FAILED"}
and I want an aggreagate output as follows
{ date:"2017-12-01T00:00:0Z", total:"2", completed:1, failed:1 }
I have tried this code but didn't produce the result as above
db.test.aggregate([
{$group: {_id : {date : '$date',status:'$status'}, total:{$sum :1}}},
{$project : {date : '$_id.date', status : '$_id.status', total : '$total', _id : 0}}
])
db.test.aggregate(
// Pipeline
[
// Stage 1
{
$group: {
_id:"$date",
total:{$sum:1},
failed:{$sum:{$cond:[{$eq:["$status","FAILED"]},1,0]}},
completed:{$sum:{$cond:[{$eq:["$status","COMPLETED"]},1,0]}}
}
},
// Stage 2
{
$project: {
date : '$_id',
total : 1,
failed : 1,
completed : 1,
_id : 0,
}
},
]
);
The following schema is given:
LogSchema {
...
likes: Number,
author: User,
created_at: Date
...
}
The following query seems to be very tricky:
Get the top X users who have the most likes for all today created logs.
The result should look like this:
User x: 1000 likes
User y: 558 likes
etc.
I have no clue how I can attack that. I know, that I could use some Aggregation, but how should it be done here, since likes are bound to users somehow.
Here is one example with commands .aggregate() used under Mongo Shell with test data
{ "_id" : ObjectId("56c912a1ebf94ca549e4ab8f"), "likes" : 123, "author" : "x", "created_at" : ISODate("2016-02-21T01:28:01.549Z") }
{ "_id" : ObjectId("56c912aaebf94ca549e4ab90"), "likes" : 120, "author" : "x", "created_at" : ISODate("2016-02-21T01:28:10.116Z") }
{ "_id" : ObjectId("56c912b4ebf94ca549e4ab91"), "likes" : 12, "author" : "y", "created_at" : ISODate("2016-02-21T01:28:20.996Z") }
{ "_id" : ObjectId("56c912bbebf94ca549e4ab92"), "likes" : 22, "author" : "y", "created_at" : ISODate("2016-02-21T01:28:27.644Z") }
Commands
> var d = new Date();
> d.setHours(0, 0, 0); // set to the first second of today, used for query today logs
> db.log.aggregate([
// query today logs by `create_at`
{$match: {created_at: {$gt: d}}},
// group by author and sum the `likes`
{$group: {_id: '$author', likes: {$sum: '$likes'}}}
]).map(function(val) {
// map the field per request
return {[val._id]: val.likes}
});
Result
[ { "y" : 34 }, { "x" : 243 } ]
With mongoose aggregate, please try it
var p = Log.aggregate([
// query today logs by `create_at`
{$match: {created_at: {$gt: d}}},
// group by author and sum the `likes`
{$group: {_id: '$author', likes: {$sum: '$likes'}}}
]).exec();
p.then(function(vals){
return vals.map(function(val) {
return {[val._id]: val.likes};
});
});
I have a collection named votes:
{
"_id" : ObjectId("54a3cb59b2b8ded51693074d"),
"Pseudo" : "Cacaboy",
"Type" : "down",
"postvote" : ObjectId("54a2f05bedbe1109145b06b6"),
"CreatedDate" : ISODate("2014-12-31T10:02:34.209Z"),
"__v" : 0
}
{
"_id" : ObjectId("54a3d776ecbf63c61a91d396"),
"Pseudo" : "CosmicJB",
"Type" : "up",
"postvote" : ObjectId("54a2f05bedbe1109145b06b6"),
"CreatedDate" : ISODate("2014-12-31T11:01:10.715Z"),
"__v" : 0
}
{
"_id" : ObjectId("54a3dca5b2b8ded51693074e"),
"Pseudo" : "hateman",
"Type" : "down",
"postvote" : ObjectId("54a2f05bedbe1109145b06b6"),
"CreatedDate" : ISODate("2014-12-31T10:02:34.209Z"),
"__v" : 0
}
Implemented Aggregation pipeline:
Vote.aggregate({$match: {postvote: pvote}},
{$group: {_id: '$Type',
n: { $sum: 1 }
}},
function(err, cb){
console.log(cb);
});
Obtained o/p:
[ { _id: 'up', n: 1 }, { _id: 'down', n: 2 } ]
Desired Result, for a postvote:
If up and down votes, both are present then result:up-down.
If just down votes are present then, result: -down.
If just up votes are present then result:up.
Is it possible using aggregation?
You need to modify your aggregation pipeline to perform the below operations:
Match the records with the desired postvote id(s).
For each record, project an extra field named weight, for the records of Type - up, the
weight would be 1, for the other -1.
Group based on the postvote field, to project the sum of the weight field for the
postvote as result.
Code:
Vote.aggregate(
{$match:{"postvote":pvote}},
{$project:{"postvote":1,"weight":{$cond:[{$eq:["$Type","up"]},1,-1]}}},
{$group:{"_id":"$postvote","result":{$sum:"$weight"}}},
function(err,data){
// handle response.
}
)
Sample o/p:
{ "_id" : ObjectId("54a2f05bedbe1109145b06b6"), "result" : -1 }