Redis, Node.JS and an Unique ID - node.js

What is the proper way to handle unique identifiers with Node.JS and Redis? I'm looking to make the switch from MongoDB/Mongoose to Redis. There I create a Document which gets a _id field. I can use that in other Documents, to link back to them. Then I can use findByID() to retrieve the document.
I'd like to accomplish the same thing in Redis.

For simplicity, let's imagine you have two types of objects in your system: users and widgets. Each of these objects will be stored in Redis as hashes. Below are the fields that each of the object types will have in their hashes:
user
id
name
parent (which user is responsible for this user in the system)
widget
id
name
owner (which user owns this widget)
The parent field of user and the owner field of widget will act like foreign keys that reference some other object by that object's ID.
With this configuration, you need a couple of other keys in your system: user:id and widget:id. These will be used as auto increment values of the user and widget IDs. Whenever new user or widget is added to the system, you will run the INCR command:
INCR user:id # new user ID
INCR widget:id # new widget ID
You will then use the returned INCR value as the primary key for the object. Here is some pseudo-code for adding a new user:
var newUserId = redis('INCR')
var newUserKey = 'user:' + newUserId
redis('HMSET', [newUserKey,
'id', newUserId,
'name', username,
'parent', parentUserId
])
You can see how the above code could be tweaked slightly for adding a new widget.
Let's say that someone requests widget #55 from your system. First we will fetch the widget with that ID, then we will fetch the widget's owner by ID. Below is the pseudo-code for this:
var widgetId = req.params.id // 55
var widgetKey = 'widget:' + widgetId
var widgetObject = redis('HGETALL', [widgetKey])
var userKey = 'user:' + widgetObject.owner
var userObject = redis('HGETALL', [userKey])
// Do something with widgetObject and userObject

Related

Proper Sequelize flow to avoid duplicate rows?

I am using Sequelize in my node js server. I am ending up with validation errors because my code tries to write the record twice instead of creating it once and then updating it since it's already in DB (Postgresql).
This is the flow I use when the request runs:
const latitude = req.body.latitude;
var metrics = await models.user_car_metrics.findOne({ where: { user_id: userId, car_id: carId } })
if (metrics) {
metrics.latitude = latitude;
.....
} else {
metrics = models.user_car_metrics.build({
user_id: userId,
car_id: carId,
latitude: latitude
....
});
}
var savedMetrics = await metrics();
return res.status(201).json(savedMetrics);
At times, if the client calls the endpoint very fast twice or more the endpoint above tries to save two new rows in user_car_metrics, with the same user_id and car_id, both FK on tables user and car.
I have a constraint:
ALTER TABLE user_car_metrics DROP CONSTRAINT IF EXISTS user_id_car_id_unique, ADD CONSTRAINT user_id_car_id_unique UNIQUE (car_id, user_id);
Point is, there can only be one entry for a given user_id and car_id pair.
Because of that, I started seeing validation issues and after looking into it and adding logs I realize the code above adds duplicates in the table (without the constraint). If the constraint is there, I get validation errors when the code above tries to insert the duplicate record.
Question is, how do I avoid this problem? How do I structure the code so that it won't try to create duplicate records. Is there a way to serialize this?
If you have a unique constraint then you can use upsert to either insert or update the record depending on whether you have a record with the same primary key value or column values that are in the unique constraint.
await models.user_car_metrics.upsert({
user_id: userId,
car_id: carId,
latitude: latitude
....
})
See upsert
PostgreSQL - Implemented with ON CONFLICT DO UPDATE. If update data contains PK field, then PK is selected as the default conflict key. Otherwise, first unique constraint/index will be selected, which can satisfy conflict key requirements.

How to Update an Object inside an Array inside a MongoDB Collection using Mongoose

This Is An Expense Tracker Application
I'm Trying to Make An Update Route where The User Can Update the Value of An Expense
For Example, I want to update the First Expense Name from Bike to Bike Rental & Amount from 250 to 500
And similarly, make a generic endpoint where the user can update any expense whenever necessary
Here A Snapshot of My Express Get Route & The Patch route which I want to fill
The ObjectID of the Entire Collection which is 607bbb07e1ebb63a3033af15 will be sent to the backend from the Frontend.
I am using Express, Mongoose.
You can run update on the model you have created like this:
const filter = {_id :"(*User Id Here*)", "Expenses._id": "(*Expense Id Here*)"}; //check the type of _id if this doesn't work
const query = {$set: {"Expenses.$.Name" : "value"}};
User.update(filter, query);
Or,
User.update({_id :"ObjectId(pass id)", "Expense._id" : ObjectId'pass id'}, {'$set': {'Expenses.$.Name': 'name update'});
Similarly, You can do this for any key in the object provided that the key exists in it. Now this will check the

Read random user firestore

Whenever a user uses the Firebase Auth to register on my app, I create a document in a users collection of Firestore that stores metadata such as pseudo, userType, gender ...
To do that, the document id is exactly the same as the uid provided automatically by Firebase Auth (from the user UserRecord object)
Now, my app needs to fetch a user randomly from the users collection in Firestore.
I read Firestore: How to get random documents in a collection but this post suggest that I create the ID myself. The app is already built using the FirebaseAuth generated ID so what is the solution ?
A common practice in firestore is to create a "--Stats--" document within a collection (--Stats-- being the document id). This document can house information about the collection (number of documents, last updated, collection privileges etc.).
In your case, you could use cloud functions/triggers to keep tract of the total number of users in the users collection and add the id of a new user to a "userIds" array. You could keep both of these fields in the users collection's --Stats-- document. This way, when you wanted to get a random user, you could randomly generate a number betweeen 0 and the document count, then use it as an index of the userIds array. I might look something like this:
var usersCollectionRef= db.collection("users");
usersCollectionRef.doc("--Stats--").get().then((doc) => {
let numberOfUsers = doc.data().numberOfUsers;
let userIdArray = doc.data().userIds;
let randomNumber = Math.floor(Math.random() * (numberOfUsers + 1));
return usersCollectionRef.doc(userIdArray[randomNumber]).get();
}).then((doc) => {
...do something with the user's document
})

Saving data on object for each user in a nosql database (Mongo)

I have a REST API which serves from a database in MongoDB. Say each JSON unit that is served contains data about a film. I'd like my users to tick whether they've seen a film or not. My problem is that, being a beginner, I am not sure how this should be implemented.
I somehow need to save this for each user. Right now my mongo database just holds all of the films in general.
Could you give me an example of how this would be accomplished in a no-sql database? What if I want to save more detailed data like when a user takes private notes related to a certain film?
You can simply have a table that has the user_id, the movie_id and the boolean, which mean if there is movie_id and a user_id the boolean is true if not it remains false thats how i would impplement it.
You can have movies data some what like this which contains unique ID for each movie
movie={
id : <MOVIE_ID> //some movie ID
name : <MOVIE_NAME> //some name
... //other info you want to store
}
then you can save each movie that user had watched in his user data in a array
user = {
id : <USER_ID> //some user id
name : <USER_NAME> //some name
watched_movies : [<MOVIE_ID1>,<MOVIE_ID2>,.....] //movie IDS
... //other data about user
}
while you rendering all movies for particular user you just need to traverse these array and mark check for movie if user have already watched that movie

Not able to access the data inside of an object

I am fetching id column value from database for a particular email. In this case I am passing email and want to get primary key i.e id. This operation is successful as I get object which contains Object with the right and expected result. However I am not able to access the object.
I am receiving object like this:
[ UserInfo { id: 21 } ]
And I am not able to access id part of it.
I am using node.js, postgres for database and typeorm library to connect with database.
const id = await userRepo.find({
select:["id"],
where: {
email:email
}
});
console.log(id)
This prints the above object.
The id I am getting is right. But I am not able to retrieve the id part of the object. I tried various ways for e.g.
id['UserInfo'].id, id.UserInfo.
Please help me in accessing the object I am receiving
Typeorm .find() returns an array of objects containing entries corresponding to your filters, in your case, all entries with an email field corresponding to the email you specified.
Because the result is an array, you can access it this way:
const records = await userRepo.find({
select: ['id'],
where: {
email,
},
})
console.log(records[0].id)
You could also use the .findOne() method, which returns a single element and might be a better solution in your case :)
When you are putting a field in the select part select:["id"], you are only retrieving this part of the database.
It is like your query was this: select id from userRepo where email = email
and you need to put * in the select part to retrieve all the information:
const id = await userRepo.find({
select:["*"],
where: {
email:email
}
});

Resources