Node.JS MongoDB Order of Operations Use Case - javascript

What is the order of operations for the mongodb-native driver?
Let's say you have a class that's purpose is to save a document of some sort and let's say it has a long life. How many times should open be called? Once per db write? When is close supposed to be called? Essentially I want a class method that looks like this:
var myMongoClass = new MongoDB(server,port)
myMongoClass.write_file(filename,callback)
myMongoClass.write_doc(doc,callback)
I posted this a while ago and got it working:
Problem with MongoDB GridFS Saving Files with Node.JS
It's now not working at all and failing with TypeError: Cannot read property 'md5' of null
Every time I work with this library I want to bang my head through a wall.

It seems like the correct answer is create a client and keep that client open for the duration of the application (never explicitly calling close). I have a wrapper that keeps a reference to the connected client and my app only boots up if the connection is received.

Related

Best way to have a Node.JS server keep updated with a FireBase database in real time?

I currently have a Node.JS server set up that is able to read and write data from a FireBase database when a request is made from a user.
I would like to implement time based events that result in an action being performed at a certain date or time. The key thing here though, is that I want to have the freedom to do this in seconds (for example, write a message to console after 30 seconds have passed, or on Friday the 13th at 11:30am).
A way to do this would be to store the date/time an action needs be performed in the database, and read from the database every second and compare the current date/time with events stored so we know if an action needs to be performed at this moment. As you can imagine though, this would be a lot of unnecessary calls to the database and really feels like a poor way to implement this system.
Is there a way I can stay synced with the database without having to call every second? Perhaps I could then store a version of the events table locally and update this when a change is made to the database? Would that be a better idea? Is there another solution I am missing?
Any advice would be greatly appreciated, thanks!
EDIT:
How I currently initialise the database:
firebase.initializeApp(firebaseConfig);
var database = firebase.database();
How I then get data from the database:
await database.ref('/').once('value', function(snapshot){
snapshot.forEach(function(childSnapshot){
if(childSnapshot.key === userName){
userPreferences = childSnapshot.val().UserPreferences;
}
})
});
The Firebase once() API reads the data from the database once, and then stops observing it.
If you instead us the on() API, it will continue observing the database after getting the initial value - and call your code whenever the database changes.
It sounds like you're looking to develop an application for scheduling. If that's the case you should check out node-schedule.
Node Schedule is a flexible cron-like and not-cron-like job scheduler
for Node.js. It allows you to schedule jobs (arbitrary functions) for
execution at specific dates, with optional recurrence rules. It only
uses a single timer at any given time (rather than reevaluating
upcoming jobs every second/minute).
You then can use the database to keep a "state" of the application so on start-up of the application you read all the upcoming jobs that will be expected and load them into node-schedule and let node-schedule do the rest.
The Google Cloud solution for scheduling a single item of future work is Cloud Tasks. Firebase is part of Google Cloud, so this is the most natural product to use. You can use this to avoid polling the database by simply specifying exactly when some Cloud Function should run to do the work you want.
I've written a blog post that demonstrates how to set up a Cloud Task to call a Cloud Functions to delete a document in Firestore with an exact TTL.

How to run Mongo JS Shell Script with DB Connection

I'm trying to write a mongo shell script that will delete some entries in an existing DB, and then reload them (depending on some conditions), and I'm having a lot of trouble.
One thing I can't understand/figure out is this:
To run the script file I'm making (let's call it script.js), I'm reading (from mongo docs and other places) that I need to use a command like this:
mongo mongodb://{{mycreds}}#{{address of existing mongo}}:27017/{{DB I want}}?authSource=admin script.js
However, since I'm connecting to that same DB in the script itself, I'm also seeing that I need to make that connection in the script.js:
db = connect(
"mongodb://{{mycreds}}#{{address where the existing mongo is}}:27017/{{DB I want}}?authSource=admin"
);
Why do I have to specify the DB connection when running the script? It's in the script?
Either way, I'm not able to make the connection in the script. I don't know if I'm running the script incorrectly, or making the connection to the DB in the script incorrectly. Or just something else.
In the docs, it says I can run the script in the mongo shell as well. But don't I have to have a mongo instance running at 27017 to start the script? And do I need a mongo running on my machine (since there's already one that exists that I need to connect to)?
I would really appreciate some clarity in this. All I'm trying to figure out is how to run a mongo script that connects to an existing DB, and I'm getting really tangled in all these docs.
Edit:
After receiving a comment (thanks Joe), I removed the connection in the script file and was able to make the connection. I guess having both was messing it up. I'd still like to be able to have the connection in the script, but not when I run the script.
I want to do this so that others can run the script without entering the long connection address.
If anyone knows a way to do this, I'd appreciate the help. Thanks.
you always need a credential for any DB you want to connect even if it's SQL. if you want to make it easier for you, you need to create a file.js in vs code and put a credential in a file when you need it you can just call it that's it, and use roboMongo to make your life easier with MongoDB.

How to make per user base logging with hapi js

I am using winston logging framework and logging on basis of log level, but now i am facing difficulties in tracking down bugs. So we decided to make logging on per user basis, and this is where i ran into problem.
What i want to acheive?
log file for every user will be generated on every hour. (We can skip every hour constraint in this thread) and every user has unique identifier 'uid'.
What i have?
I have followed architecture as used here 'https://github.com/agendor/sample-hapi-rest-api'. Some additional lib modules exist too.
Currently i am using winston library (but i can afford to replace this if needed).
Brief introduction of flow
Currently, i have access to request object in handler function only, but i want to log events in DAO, library functions too ( on per user basis). 'Uid' is available to me in handler function in request object as i put uid in request in authentication middleware.
My solution (which is not elegant)
pass request object ( or only uid) to every function and log (using winston) event. Custom transport will determine where (in which file, on basis of uid) to put the log.
Certainly, this is not elegant way as every function must have uid parameter in order to log event, which seems bad.
What i want from you?
A better, elegant approach which is scalable too.
Related post: https://github.com/hapijs/discuss/issues/51
Try taking a look at Continuation-Local Storage:
https://github.com/othiym23/node-continuation-local-storage
Heres a good article on implementing it within express:
https://datahero.com/blog/2014/05/22/node-js-preserving-data-across-async-callbacks/

Retrieving replica set status in Mongoose

I am building a Node.js application, which reads from a MongoDB cluster. The application uses Mongoose to communicate with Mongo.
I would like to build a functionality, which is able to tell me, what does the mongoose know about the MongoDB replica set real-time (like calling rs.status()), but so far I was not able to find any kind of informations around the internet.
The purpose of this would be to be able to monitor, if something was changed in the replica set, and report it back if needed.
The problem is, I've found so far nothing on the internet in this subject. Does anyone have any idea on how to start it? It would be nice, if I could use the current mongoose connections for this purpose.
You can do this, but you need to be connected to the "admin" database and you will probably want a different connection for this other than what the rest of your application uses. Something like:
var mongoose = require("mongoose");
mongoose.connect(
"mongodb://localhost:27017,localhost:27018,localhost:27019/test");
var conn = mongoose.createConnection(
"mongodb://localhost:27017,localhost:27018,localhost:27019/admin");
conn.on("open",function() {
conn.db.command({"replSetGetStatus":1 },function(err,result) {
console.log( result );
});
});
It is important to wait for the connection to be established as well, hence the "event" callback. Mongoose will internally "queue" it's own methods operations until a connection is made, but this does not apply when grabbing a handle to the native db object and executing methods from that.

Adding a user to PFRelation using Parse Cloud Code

I am using Parse.com with my iPhone app.
I ran into a problem earlier where I was trying to add the currently logged in user to another user's PFRelation key/column called "friendsRelation" which is basically the friends list.
The only problem, is that you are not allowed to save changes to any other users besides the one that is currently logged in.
I then learned, that there is a workaround you can use, using the "master key" with Parse Cloud Code.
I ended up adding the code here to my Parse Cloud Code: https://stackoverflow.com/a/18651564/3344977
This works great and I can successfully test this and add an NSString to a string column/key in the Parse database.
However, I do not know how to modify the Parse Cloud Code to let me add a user to another user's PFRelation column/key.
I have been trying everything for the past 2 hours with the above Parse Cloud Code I linked to and could not get anything to work, and then I realized that my problem is with the actual cloud code, not with how I'm trying to use it in xcode, because like I said I can get it to successfully add an NSString object for testing purposes.
My problem is that I do not know javascript and don't understand the syntax, so I don't know how to change the Cloud Code which is written in javascript.
I need to edit the Parse Cloud Code that I linked to above, which I will also paste below at the end of this question, so that I can add the currently logged in PFUser object to another user's PFRelation key/column.
The code that I would use to do this in objective-c would be:
[friendsRelation addObject:user];
So I am pretty sure it is the same as just adding an object to an array, but like I said I don't know how to modify the Parse Cloud Code because it's in javascript.
Here is the Parse Cloud Code:
Parse.Cloud.define('editUser', function(request, response) {
var userId = request.params.userId,
newColText = request.params.newColText;
var User = Parse.Object.extend('_User'),
user = new User({ objectId: userId });
user.set('new_col', newColText);
Parse.Cloud.useMasterKey();
user.save().then(function(user) {
response.success(user);
}, function(error) {
response.error(error)
});
});
And then here is how I would use it in xcode using objective-c:
[PFCloud callFunction:#"editUser" withParameters:#{
#"userId": #"someuseridhere",
#"newColText": #"new text!"
}];
Now it just needs to be modified for adding the current PFUser to another user's PFRelation column/key, which I am pretty sure is technically just adding an object to an array.
This should be fairly simple for someone familiar with javascript, so I really appreciate the help.
Thank you.
I would recommend that you rethink your data model, and extract the followings out of the user table. When you plan a data model, especially for a NoSQL database, you should think about your queries first and plan your structure around that. This is especially true for mobile applications, as server connections are costly and often introduces latency issues if your app performs lots of connections.
Storing followings in the user class makes it easy to find who a person is following. But how would you solve the task of finding all users who follow YOU? You would have to check all users if you are in their followings relation. That would not be an efficient query, and it does not scale well.
When planning a social application, you should build for scalabilty. I don't know what kind of social app you are building, but imagine if the app went ballistic and became a rapidly growing success. If you didn't build for scalability, it would quickly fall apart, and you stood the chance of losing everything because the app suddenly became sluggish and therefore unusable (people have almost zero tolerance for waiting on mobile apps).
Forget all previous prioities about consistency and normalization, and design for scalability.
For storing followings and followers, use a separate "table" (Parse class) for each of those two. For each user, store an array of all usernames (or their objectId) they follow. Do the same for followers. This means that when YOU choose to follow someone, TWO tables need to be updated: you add the other user's username to the array of who you follow (in the followings table), and you also add YOUR username to the array of the other user's followers table.
Using this method, getting a list of followers and followings is extremely fast.
Have a look at this example implementation of Twitter for the Cassandra NoSQL database:
https://github.com/twissandra/twissandra

Categories

Resources