Mongodb / JS: find the minimum (earliest) date - javascript

I'm trying to find the minimum date of all documents in a collection. I have approached this so far with a sort function and taking the first one that I find, see here:
earliestTime = function (kitUser) {
'use strict';
var res, earliestTime;
res = Cards.findOne({ kit: kitUser }, { fields: { created: 1 } }, { sort: { created: 1 } });
console.log('Created date: ' + res.created);
earliestTime = new Date(res.created - 20000);
console.log('Earliest time: ' + earliestTime);
return earliestTime;
};
I then subtract 20 seconds from the value I've found and return that value to insert a new document which has 20 seconds less in the created fields than the earliest I've found before.
modifierObject = {};
modifierObject.created = earliestTime(kitUser);
The function earliestTime delivers the right results when I look at the console output:
I20160516-15:53:14.849(7)? Created date: Wed Apr 06 2016 12:00:11 GMT+0700 (ICT)
I20160516-15:53:14.849(7)? Earliest time: Wed Apr 06 2016 11:59:51 GMT+0700 (ICT)
However, when this function is called 21 times with a couple of read/write operations in between each call, each inserted document has the same timestamp in the created field:
{ "_id" : "xcd3EfKfS6iLGvcsP", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "bvL3f8NHHZM8Ytdma", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "gAirEbicdWJz9CELB", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "kgAg6Jt2P89mTJYgN", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "xeqR5K2fxNmgEv4bb", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "PgPimNRxj2zBuS8M2", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "snwEWeXpn4Ampsito", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "8RCS8YQLxY7tY6Ruk", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "tEqRJs49RNvCzkMz6", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "PJnZ7Z4WH6rTTw626", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "J2L6KPhzxcva3rttJ", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "YR5R6ShakPxCXgj54", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "Ajd6D8E8WrRB47q7d", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "g5CQgjbPH7NoytyMw", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "s9NgtsiR7WbjgeKLr", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "NPtZMHkAdqySShD3a", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "XxpWREjutAjbgHyME", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "6ZsiL2ZgidWjk3cgb", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "pvXiEaJgkuHEKijbB", "created" : ISODate("2016-04-06T04:59:51.183Z") }
{ "_id" : "im4GzumrE6RARNLbe", "created" : ISODate("2016-04-06T04:59:51.183Z") }
I'm puzzle as to how this can happen. The result which I was expecting would be (timestamps):
"created" : ISODate("2016-04-06T04:59:51.183Z")
"created" : ISODate("2016-04-06T04:59:41.183Z")
"created" : ISODate("2016-04-06T04:59:31.183Z")
"created" : ISODate("2016-04-06T04:59:21.183Z")
I suspect it's something wrong with my function with the sort, hence my question how I can easier find the minimum of a date in MongoDB.
Thanks in advance!

Ok, I've found an error in my projection, the 4th line has to be:
res = Cards.findOne({ kit: kitUser }, { fields: { created: 1 }, sort: { created: 1 } });
I've overlooked that the projection is one object and therefore the first bracket has to be around all the options like fields and sort.
This article has been very helpful in identifying it and thanks to Marcel Fahle for pointing to it:
https://themeteorchef.com/snippets/mongodb-queries-and-projections/

Related

Mongoose aggregate query working as a mongodb query but not able to convert to mongoose

Below is my JSON structure
[{
"_id" : ObjectId("626204345ae3d8ec53ef41ee"),
"categoryName" : "Test Cate",
"__v" : 0,
"createdAt" : ISODate("2022-04-22T01:26:11.627Z"),
"items" : [
{
"itemName" : "Cate",
"user" : ObjectId("6260729af547915d9d876c23"),
"itemDescription" : "slkkndanslk",
"itemImage" : "/images/camping-table.jpeg",
"_id" : ObjectId("626204339b24b2ead6c05a70"),
"updatedAt" : ISODate("2022-04-22T01:26:11.627Z"),
"createdAt" : ISODate("2022-04-22T01:26:11.627Z")
}
],
"updatedAt" : ISODate("2022-04-22T01:26:11.627Z")
},
{
"_id" : ObjectId("62620e725ae3d8ec53ef4aa8"),
"categoryName" : "sdsad",
"__v" : 0,
"createdAt" : ISODate("2022-04-22T02:09:54.028Z"),
"items" : [
{
"itemName" : "asdada",
"user" : ObjectId("62620e6299145edb95147482"),
"itemDescription" : "asdsadad",
"itemImage" : "/images/camping-table.jpeg",
"_id" : ObjectId("62620e7299145edb95147486"),
"updatedAt" : ISODate("2022-04-22T02:09:54.028Z"),
"createdAt" : ISODate("2022-04-22T02:09:54.028Z")
},
{
"itemName" : "dsdsa",
"user" : ObjectId("62620e6299145edb95147482"),
"itemDescription" : "adasdad",
"itemImage" : "/images/camping-table.jpeg",
"_id" : ObjectId("62621b9c3662e0b4acabb71f"),
"updatedAt" : ISODate("2022-04-22T03:06:04.727Z"),
"createdAt" : ISODate("2022-04-22T03:06:04.727Z")
}
],
"updatedAt" : ISODate("2022-04-22T03:06:04.727Z")
}]
This is just one document and there would be array of documents. Also there may be multiple items within the same category.
I want to fetch all the items in all category with a particular userid. In MongoDB below is my query which is giving correct output on mongo shell
db.trades.aggregate([
{
$unwind: "$items"
},
{
$match: {
"items.user": ObjectId("6260729af547915d9d876c23")
}
}
]).pretty()
In mongoose I am doing the following thing but not getting the result
tradeModel.aggregate([ { $unwind : "$items" }, { $match : { "items.user" : id } } ])
.then(res => {
console.log(JSON.stringify(res))
})
Let me know what I am missing
Your parameter id is type string but mongodb store type ObjectId
change
tradeModel.aggregate([ { $unwind : "$items" }, { $match : { "items.user" : id } } ])
.then(res => {
console.log(JSON.stringify(res))
})
into
tradeModel.aggregate([ { $unwind : "$items" }, { $match : { "items.user" : {"$oid": id} } } ])
.then(res => {
console.log(JSON.stringify(res))
})
Got the answer we can use ObjectId(id) in search like this
tradeModel.aggregate([ { $unwind : "$items" }, { $match : { "items.user" : ObjectId(id) } } ])
.then(res => {
console.log(JSON.stringify(res))
})

How can we find the recent record from each group in mongodb?

I want to find out most recent record from each group.
My collection:-
{ "_id" : ObjectId("1"), "loginID" : Ram.1234#gmail.com , "name" : Ram, "date" : ISODate("2017-02-01T00:00:00Z"),Site:blog.com,opertion:modified }
{ "_id" : ObjectId("2"), "loginID" : Arjun34#gmail.com, "name" : Arjun, "date" : ISODate("2017-02-01T00:00:00Z").site:ketanblog.com,opertion:updated }
{ "_id" : ObjectId("3"), "loginID" :Ram.1234#gmail.com , "name" : Ram, "date" : ISODate("2017-02-03T00:00:00Z"),Site:blogtec.com,opertion:modified }
{ "_id" : ObjectId("4"), "loginID" : Arjun34#gmail.com, "name" : Arjun, "date" : ISODate("2017-02-08T00:00:00Z"),Site:blogpec.com,opertion:updated }
{ "_id" : ObjectId("5"), "loginID" : Arjun34#gmail.com, "name" : Arjun, "date" : ISODate("2017-02-07T00:00:00Z") ,Site:blog.com,opertion:read}
{ "_id" : ObjectId("6"), "loginID" : shyam78#gmail.com, "name" : Shyam, "date" : ISODate("2017-02-09T00:00:00Z"),site:ketanblog.com,opertion:deleted }
{ "_id" : ObjectId("7"), "loginID" : shyam78#gmail.com, "name" : Shyam, "date" : ISODate("2017-02-03T00:00:00Z") ,site:ketanblog.com,opertion:updated}
{ "_id" : ObjectId("8"), "loginID" : Arjun34#gmail.com, "name" : Arjun, "date" : ISODate("2017-02-03T00:00:00Z"),Site:blogtrt.com,opertion:read }
My Expected output:-
{ "_id" : ObjectId("3"), "loginID" : Ram.1234#gmail.com, "name" : Ram, "date" : ISODate("2017-02-03T00:00:00Z"),Site:blogtec.com,opertion:modified }
{ "_id" : ObjectId("4"), "loginID" : Arjun34#gmail.com, "name" : Arjun, "date" : ISODate("2017-02-08T00:00:00Z"),Site:blogpec.com,opertion:updated }
{ "_id" : ObjectId("6"), "loginID" : shyam78#gmail.com, "name" : Shyam, "date" : ISODate("2017-02-09T00:00:00Z"),Site:ketanblog.com,opertion:deleted }
Sort by date to keep the latest data for each group at the top
Group by login id, get the first record for each group which is latest. It discards other records in each group
db.coll.aggregate([
{
$sort : {"$date": - 1}
},
{
$group: {
_id : "$loginID",
data : {
$first : "$$ROOT"
}
}
}
])
You can try,
$sort by date descending order
$group by loginID and add first recent document in recent
$replaceRoot to replace recent into new root
$sort new grouped documents
db.collection.aggregate([
{ $sort: { date: -1 } },
{
$group: {
_id: "$loginID",
recent: { $first: "$$ROOT" }
}
},
{ $replaceRoot: { newRoot: "$recent" } },
{ $sort: { date: -1 } }
])
Playground

Is there a way I can update mongodb document without a loop ie. with array as condition?

this is my document
{ "_id" : ObjectId("5ef05c35743df0112cbf5729"),
"doctor" : ObjectId("5e2ef5fd55e8c1043895aaf1"),
"patient" : ObjectId("5e0378d9a88e67364426be55"),
"requests" : [ { "_id" : ObjectId("5ef05c35743df0112cbf572d"),
"labTestType" : ObjectId("5ee752b9e26cbb3440b9259e"),
"result" : "",
"paymentstatus" : "Unpaid",
"createdAt" : ISODate("2020-06-22T07:22:29.664Z"),
"updatedAt" : ISODate("2020-06-22T07:22:29.664Z") },
{ "_id" : ObjectId("5ef05c35743df0112cbf572c"),
"labTestType" : ObjectId("5ee752b9e26cbb3440b925a6"),
"result" : "",
"paymentstatus" : "Unpaid",
"createdAt" : ISODate("2020-06-22T07:22:29.664Z"),
"updatedAt" : ISODate("2020-06-22T07:22:29.664Z") },
{ "_id" : ObjectId("5ef05c35743df0112cbf572b"),
"labTestType" : ObjectId("5ee752b9e26cbb3440b925b5"),
"result" : "",
"paymentstatus" : "Unpaid",
"createdAt" : ISODate("2020-06-22T07:22:29.664Z"),
"updatedAt" : ISODate("2020-06-22T07:22:29.664Z") },
{ "_id" : ObjectId("5ef05c35743df0112cbf572a"),
"labTestType" : ObjectId("5ee752b9e26cbb3440b925b6"),
"result" : "",
"paymentstatus" : "Unpaid",
"createdAt" : ISODate("2020-06-22T07:22:29.664Z"),
"updatedAt" : ISODate("2020-06-22T07:22:29.664Z") }
],
"createdAt" : ISODate("2020-06-22T07:22:29.664Z"),
"updatedAt" : ISODate("2020-06-23T06:35:06.420Z"), "__v" : 0 }
I want to update paymentstatus under requests to Paid by providing labTestType
Objectids as list of array.
Try this code this works for me
db.getCollection('your_collection').findOneAndUpdate(
{
$and: [
{ _id: new ObjectId(_id) }, //_id = "5ef05c35743df0112cbf5729"
{ 'requests.labTestType': { $in: [new ObjectId('5ee752b9e26cbb3440b9259e'), new ObjectId('5ee752b9e26cbb3440b925b5')] } }]
},
{
$set: { 'requests.$.paymentstatus': 'paid'
} //set new payment status
})
this worked for me i was missing $in property
db.getCollection('your_collection').updateMany(
{_id: newObjectId(_id)},
{$set: {"requests.$[element].paymentstatus": "Paid"}},
{ multi:true,
arrayFilters: [{ "element.labTestType": {$in: arraywithobjectIds}}]
})

Mongoose (MongoDB) - Error: Can't use $each with Number

I've to push a given array of Number values into a selected Document inside my MongoDB database.
The Document that I'm going to update as the following structure:
{
"_id" : {
"id" : 17,
"type" : "f"
},
"__v" : 0,
"created_at" : ISODate("2017-03-22T11:16:21.403Z"),
"token" : {
"expDate" : ISODate("2017-12-31T00:00:00Z"),
"token" : "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJlbWFpbCI6ImFsYWRpbkBjb25zb3J6aW9jZXIuaXQiLCJleHAiOjE1MTQ2Nzg0MDB9.QvbT146bA_KH5XA7MH8ASXm9cr3sPZChJ3prYyDireI"
},
"updated_at" : ISODate("2017-07-24T09:42:33.741Z"),
"plots" : {
"idPlot" : [
23570,
23475
]
},
"machines" : [
{
"idPlotBind" : 1,
"ip" : "",
"mac" : "18-5F-00-4A-FE-F4",
"irrId" : 31,
"_id" : ObjectId("59084f527d634d301338aac6"),
"addr" : "pialadin.ddns.net"
},
{
"idPlotBind" : null,
"ip" : "",
"mac" : "12-01-02-FE-AB-B2",
"irrId" : 35,
"_id" : ObjectId("59084f7d7d634d301338aac7")
}
]
}
I'm using the Mongoose library for JS, and the accused query is this one:
userSchema.findOneAndUpdate({$and:[{ '_id.id': resData.PlotRows.IdUser}, {'_id.type': 'f'}]},{$addToSet:{'plots.$.idPlot': {$each: plotData}}}, {upsert: false}, function(err, usr){
if(err){
console.log(err);
return;
}
});
But when I try to execute it, gives me back:
Error: Can't use $each with Number

MongoDB Range Issue

I'm using nodejs and mongodb.
I want to search docs between a num range but the function always give me number that outside the range. For example, this is my function and I want to get the results of the docs that they has a field size with the numbers between 1 to 1200:
db.collection(example).find({
size: {
"$gte": 1,
"$lte": 1200
}
}).toArray(function(err, results) {
db.close();
console.log("results=" + results);
});
the doc in the Database:
{ "_id" : ObjectId("56659a492b9eaad2d9e6d4d2"), "size" : -1 }
{ "_id" : ObjectId("56659a492b9eaad2d9e6d4d3"), "size" : 100 }
{ "_id" : ObjectId("56659a492b9eaad2d9e6d4d4"), "size" : 800 }
{ "_id" : ObjectId("56659a492b9eaad2d9e6d4d5"), "size" : 1999 }
the result of the query should be:
{ "_id" : ObjectId("56659a492b9eaad2d9e6d4d3"), "size" : 100 }
{ "_id" : ObjectId("56659a492b9eaad2d9e6d4d4"), "size" : 800 }
but the query result is:
{ "_id" : ObjectId("56659a492b9eaad2d9e6d4d2"), "size" : -1 }
{ "_id" : ObjectId("56659a492b9eaad2d9e6d4d3"), "size" : 100 }
{ "_id" : ObjectId("56659a492b9eaad2d9e6d4d4"), "size" : 800 }
{ "_id" : ObjectId("56659a492b9eaad2d9e6d4d5"), "size" : 1999 }
I believe you need to use a $and clause on your size conditions. It might look something like this:
db.collection(example).find( {
$and: [
{ size: { $gte: 1 } },
{ size: { $lte: 1200 } }
] } ).toarray...
See the examples in the mongo docs here.
Edit: Actually, an implicit and was fine. As noted, the actual problem here was size values were stored as strings, not ints.

Categories