MongoDB: How to get timestamp and ObjectID from newest document in collection? - node.js

I would like to get last created documents in collection and return their objectID and timestamps. For example if yesterday I created 10 documents I would like to return them with db.collection and then
const lastTimeStamp = will be the timestamp from the last created element
const lastTimeStampArray = will be array of timestamps from yesterdays records
const lastObjectId = will be ObjectID of last created document
const lastObjectIdsArray = array of last objectIds
I am using:

MongoDB's _id field has info about date stored in itself. The timestamp is contained in the first 4 bytes of a mongoDB id.
You can use ObjectId.getTimestamp() function to get time from _id of a document.
Sorting on an _id field that stores ObjectId values is roughly equivalent to sorting by creation time.
For you question:
// To get lastTimeStamp
db.collection.find().sort({ '_id': -1}).limit(1).forEach(
function(doc){
lastTimeStamp = doc._id.getTimestamp();
}
)
// to get lastObjectId
db.collection.find().sort({ '_id': -1}).limit(1).forEach(
function(doc){
lastObjectId = doc._id;
}
)
Now, to get all records inserted yesterday might be a bit of hard work. You need to extract all records inserted yesterday and from that you need to extract information you need.
// to get lastTimeStampArray and lastObjectIdsArray
var yesterdayStart = new Date();
yesterdayStart.setDate(yesterdayStart.getDate() - 1);
yesterdayStart.setHours(0,0,0,0);
var startId = Math.floor(yesterdayStart.getTime() / 1000).toString(16) + "0000000000000000";
var yesterdayEnd = new Date();
yesterdayEnd.setDate(yesterdayEnd.getDate() - 1);
yesterdayEnd.setHours(23,59,59,999);
var endId = Math.floor(yesterdayEnd.getTime() / 1000).toString(16) + "0000000000000000";
var lastTimeStampArray = [];
var lastObjectIdsArray = [];
db.collection("records")
.find( { _id: {
$gte: ObjectId(startId),
$lte: ObjectId(endId)
}
}
).forEach(
function(doc){
lastObjectIdsArray.push(doc._id);
lastTimeStampArray.push(doc._id.getTimestamp());
});
These are mongo shell commands you can write your node.js accordingly.

You can get last inserted record with timestamp using the following:
db.collection.find().sort({ '_id': -1 }).limit(1).forEach(
function(doc){
print("record:"+doc._id.getTimestamp());
})
_id is the Mongodb objectID

Related

How to query by date on cloud function?

I'm trying to query some data that is between two dates, but nothing seems to work. These are my dates, I saw on a post that the division by 1000 should work , but it's not. Ive tried firebase.firestore but says firebase it's not defined but I don't know how to simply reference to firebase.firestore.Timestamp
let now = new Date()
let yesterday = Math.round((new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1).getTime())/1000)
now = Math.round(now.getTime()/1000)
This is my query attempt. Nothing works and it just returns my empty array because the query has no data to iterate through the forEach.
let snapshot = await db.collection('appointments')
.where('status', '==', 'Pending')
.where('startDate', '<=', now)
.where('startDate', '>', yesterday)
.get().then(docs => {
docs.forEach(snapshot => {
console.log(snapshot.id, '=>', snapshot.data());
console.log(snapshot.data()['doctor']);
doctor_mail.push(snapshot.id)
doctor_mail.push(snapshot.data())
});
return doctor_mail
}).
catch(err => {
return res.send(err)
});
console.log(doctor_mail)
res.send(snapshot)
The query is not returning anything because there is nothing to return. If you are querying for a string representing a date and the data is a timestamp in the Firestore, so in order to know that, it would be need to check a sample document to compare, since in the first part of your question you mentioned that you want to get a Firestore timestamp, you can do it with this code:
const timestamp = db.FieldValue.serverTimestamp();
//if you want it as a date object
const date = timestamp.toDate();
As per what you asked in the comments, for getting the value of Today and Yesterday in Timestamp you can do the following:
var todayTimestamp = timestamp.now();
var date = new Date().setDate(date.getDate() - 1);
var yesterdayTimestamp = timestamp.fromDate(date);
And convert them back to date so you can operate them if needed, you can check more details on the Timestamp in this Documentation
Okay, the thing here was that I was wrongly calling db as const db = firebase.firestore.
Instead I just had to go for:
const db = admin.firestore()

Mongoose find not match ids from array which passed

I'm stuck in mongoose query. I've an array of ids as input, I want to search that array of ids in a database for matching elements. It returns perfect result after using $in in find query.
Now, I want that Ids from an array which is not found in the database. what is the best way to do it?
Please try to comment it.
Template.find({
_ids : [
"as6d87as67da7s8d87a87", // available in database
"as6dasd8sa9d8a9a9s8d7", // not-available in database
"6756asd5as6dsadghasd3", // available in database
]
}, function(err, result){
// Need result as "as6dasd8sa9d8a9a9s8d7", which is not matched. or in object.
// Can we do with `aggregate` query?
});
I think this makes what you want
var _ids = [
"as6d87as67da7s8d87a87",
"as6dasd8sa9d8a9a9s8d7",
"6756asd5as6dsadghasd3"
];
Template.find({
_ids : _ids
}, function(err, result){
var filteredResult = _ids.filter(currentId => !result.some(item => item._id.toString() == currentId));
});
Answer by David will work. The idea here is to compare _ids array with the _ids in the result and return the missing ones. Adding more code just for understanding purposes:
Push _id of result into a new array
Compare _ids and the new array to return missing elements
var resIDs = new Array();
for (var i = 0; i < result.length; i++) {
resIDs.push(result[i]._id.toString());
}
var resultFiltered =
_ids.filter(function (v) {
return !resIDs.includes(v.toString());
})

Aggregate returns empty array

Using mongoose's Model.aggregate() returns an empty array.
I've essentially copied the format as seen here.
var match = {};
var project = {};
project["_id"] = 0;
project["products.totalprice"] = 1;
project["line"] = "$products.closedate";
ThisCollection.aggregate([
{$match: match},
{$project: project},
{$group: {
_id: "$line"
}}
], function(err, docs){
console.log(docs); //!! Returning []
});
My schema is essentially a name and _id field with a nested array of products with totalprice, closedate and some other fields.
There are most certainly a plethora of entries (some 130,000 records). Can anyone spot an issue with this?
I have created this dummy data to represent a skeleton of your schema:
db.data.save({name:"a",products:{totalprice:1,closedate:1}})
db.data.save({name:"b",products:{totalprice:2,closedate:2}})
This query does return two records and is identical to yours when inserting the JSON string for the JavaScript variable project
ThisCollection.aggregate([{$match:{}},{$project:{"_id":0,"products.totalprice":1,line:"$products.closedate"}},{$group:{_id:"$line"}}])

Loop through Mongo Collection and update a field in every document

I have Dates in one Collection that were inserted incorrectly, and are in a simple "2015-09-10" string format.
I'd like to update them to correct ISO Date format.
I've tried looping through Mongo with forEach() but I don't know the shell well enough on how to update each document in the collection.
So far I'm at this point:
db.getCollection('schedules').find({}).forEach(function (doc) {
doc.time = new Date( doc.time ).toUTCString();
printjson( doc.time );
// ^ This just prints "Invalid Date"
// Also none of the below work when I try saving them
//doc.save();
//db.getCollection('schedules').save(doc);
});
What's missing here?
The best way to do this is using "Bulk" operations
var collection = db.getCollection('schedules');
var bulkOp = collection.initializeOrderedBulkOp();
var count = 0;
collection.find().forEach(function(doc) {
bulkOp.find({ '_id': doc._id }).updateOne({
'$set': { 'time': new Date(doc.time) }
});
count++;
if(count % 100 === 0) {
// Execute per 100 operations and re-init
bulkOp.execute();
bulkOp = collection.initializeOrderedBulkOp();
}
});
// Clean up queues
if(count > 0) {
bulkOp.execute();
}
Just write a for loop using .find(), and update each result. For instance, in Python/PyMongo, let's assume we have a collection called 'movies' that we want to update by adding a field called 'reviews', whose value we want to be an array of five objects with 'name' and 'rating' fields. we'll use Faker and random to create some random info for these fields:
from pymongo import MongoClient
from faker import Faker
faker = Faker()
import random
client = MongoClient()
db = client.test
for res in db.movies.find():
db.movies.updata_one(res, {'$set':{'reviews':[{'name':faker.name(), 'rating': random.randint(1,5)} for _ in range(5)]}})
Note that if you're using native Mongo, then you should be using updateOne instead of update_one. I presume a similar approach works in JavaScript, just using for (let res of db.movies.find()) syntax

mongoose, getting object's id after using collection.insert

I'm trying to get the object id after adding it to the db (using collection.insert)
mongoose.model('Persons').collection.insert(person, function(err, newPerson) {
console.log('lets see you', newPerson);
});
and from the console I'm getting only result: { ok: 1, n: 1 } in stand of the new obj, any ideas how can I rich to the new object ?
thanks!
You can use save() here
var Persons = mongoose.model('Persons');
var personJSON = {
..... // persons schema values you want to insert
};
var person = new Persons(personJSON);
var result = yield person.save();
result variable will contain all the fields you inserted along with _id

Resources