Inappropriate Redis Database Design - javascript

I have a node.js API that is responsible for 3 things:
Registering a buyer
Getting a buyer with ID
Finding the matching buyer's offer based on some criteria
Details here
Since I'm new to Redis, I started the implementation like this:
JSON.stringify the buyer and store it with SET
Store all buyer's offers as ordered set (this is for the third endpoint, which requires the offer with the highest value) - this set contains string that represents the name of a hash
Then, that hash stores strings that represent the names of sets that have certain values and a location which the user will be redirected to after these conditions have been fulfilled (buyer1_devices, buyer1_hours, etc.)
Now, here is the problem:
I need to get GET /route working. As described on GitHub page that I have provided, I have 3 parameters: a timestamp, devices, and states. I have to browse through all the sets and get the appropriate location to redirect a user to. The location is stored in a hash, but I have to browse through all the sets. Since this is probably a bad implementation, where did it all go wrong and to go about implementing this?
Note that this is a redis problem, not a node one. I need instructions on how to go about implementing this in Redis, and then I will be ready to code it in Node.
Thank you in advance

The first rule of Redis: store the data just like you want to read it.
To answer the /route query you need "filteration" on two attributes of from the buyers' offers - state and device. There is more than one way to skin that cat, so here's one: use many Sorted Sets for the offers.
Each such offers Sorted Set key name could look like this: <device>:<state> (so the example offered in the git will be added to the key desktop:CA).
To query, use the route's arguments to compose your key's name, then proceed regularly to find the highest-scored offer and resolve the buyer's details in the Hash.
Now go get that job!

Related

Generate a unique id in react that persist

I need to keep a unique identifier for each client using my react app.
doing this will regenerate a random string (what I want) but does this on each refresh which is not what I want
const [id] = useState(Math.random().toString(36).substr(2, 8));
I've found uniqueId() form lodash but I'm afraid the id's won't be unique across multiple clients as it only give a unique Id and increment it at every call (1, 2, 3...)
const [id] = useState(_uniqueId());
Is there some kind of _uniqueId that generates a random string and also persist through page refresh?
I don't think there is a built-in or out-of-the-box solution that generates unique id in react that persist automatically. You have two problems to solve.
How to generate unique id. Which was already solved by using the uuid.
And how to persist it.
There are plenty of storage you can use depend on your need. Here's few of them where you can persist your data assuming you want it to be stored in client side.
LocalStorage
SessionStorage
Cookie
IndexedDB API
FileSystem
Again, it depends on your use case. So, carefully check them out which one fits on your requirement.
Another way to generate a temporary ID that would be the same for the same client, without storing it is to use browser fingerprinting.
For example, you can take user-agent, client timezone, and screen resolution, apply some hash function to them and call it an ID.
There are more advanced ways of fingerprinting that would result in less chance of two different users having the same ID, but it'll never be a 0% chance.
You also might want to use some libraries, such as https://github.com/fingerprintjs/fingerprintjs for this.

How to write data into a specific location Firebase Web

I want to write data into a specific location in the database. Let's say, I have a couple of users in the database. Each of them has their own personal information, including their e-mails. I want to find the user based on the e-mail, that's to say by using his e-mail (but I don't know exactly whose e-mail it is, but whoever it is do something with that user's information). To be more visible, here is my database sample.
Now, while working on one of my javascript files, when the user let's say name1 changes his name, I update my object in javascript and want to replace the whole object under ID "-LEp2F2fSDUt94SRU0cx". To cut short, I want to write this updated object in the path ("Users/-LEp2F2fSDUt94SRU0cx") without doing it by hand and just "knowing" the e-mail. So the logic is "Go find the user with the e-mail "name1#yahoo.com" and replace the whole object with his new updated object". I tried to use orderByChild("Email").equalTo("name1#yahoo.com").set(updated_object), but this syntax does not work I guess. Hopefully I could explain myself.
The first part is the query, that is separate from the post to update. This part is the query to get the value:
ref.child('users').orderByChild("Email").equalTo("name1#yahoo.com")
To update, you need to do something like this once you have the user id from the query result:
ref.child('users').child(userId).child("Email").update(newValue);
firebase.database.Query
A Query sorts and filters the data at a Database location so only a
subset of the child data is included. This can be used to order a
collection of data by some attribute (for example, height of
dinosaurs) as well as to restrict a large list of items (for example,
chat messages) down to a number suitable for synchronizing to the
client. Queries are created by chaining together one or more of the
filter methods defined here.
// Find all dinosaurs whose height is exactly 25 meters.
var ref = firebase.database().ref("dinosaurs");
ref.orderByChild("height").equalTo(25).on("child_added", function(snapshot) {
console.log(snapshot.key);
});

Parse.com Class Update From API

I have a Parse Class called Currency that provides static exchange rates using the exact format from https://openexchangerates.org/. I do not need the rates "real time" so I would like to somehow GET the info using cloud code/scheduled job once a day and then overwrite the existing entry in Currency. When users query against the rates throughout the day, it uses the Parse class and not an API call to https://openexchangerates.org. Can overwriting a class or an object in the class be done in Parse.com? If not, are there suggestions on how to go about this? Thanks in advance.
Create your job and set it to run once a day as required. In the job, make the http request. Iterate the result received to process each conversion. For that conversion, run a query to find the existing item in the data store (if one exists) by matching the conversion currencies. Update this object or create a new one if no match was found.
An alternative would be to batch delete all conversions before processing the result. This isn't great though as it leaves a finite time when no conversions will be available to users and if there is an error not even an old conversion will be available.

Javascript How to scale Array, prevent errors from undefined

I am currently creating a quiz app in meteor. One of the key variables Im using is called currentQuestions which keeps track of the questionnumber of each quiz the user has taken. It is currently an array which updates (in a Meteor session) everytime the user clicks the next or back button on a particular quiz. for example:
currentQuestion = Session.get('currentQuestion') || [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
This works fine for a small amount of quizzes. What would you suggest however when I want to have a large amount of quizzes? Currently when I create more quizzes than I have previously defined in the currenQuestion Array the app crashes.
Possible solution I have thought of
(Ugly solutions) Create a for loop that fills up the currentQuestion array with a large amount of zero's at startup.
Insert a object into the mongoDB database that contains the currentquestion with the id of the quiz that's taken (so getting rid of the array entirely)
Hope you can help.
Option 2 is definitely the right one:
If you don't need to keep track of scores between sessions, you can just use a client-side-only database and store objects as you suggest and it will be only a couple of lines of new code for a much more flexible outcome.
This would then be very easy to convert into a persistent store as well: either add sign-in with Meteor's accounts package, add the current userId to each quiz object, and then only publish the quiz objects with the same userId as the logged-in user. Alternatively, you could even use the amplify package to store results between sessions in a given browser if you wanted to avoid user login entirely (you'd have to pull existing results out again on startup, but this is very easy).
The result would have all the reactivity of a Session variable built in, and would avoid the need to populate an array with an arbitrary and changing number of zeros - just check whether the a document with the given quiz Id is in the collection or not, and if not then create it.
You'll need to get rid of the array entirely. If you are going to keep track between sessions then you'll need to go with something like mongoDB. You could created something like a progress or completion model which can hold info about the quizzes they have taken and progress for each. Once you have that stores those by some userId related key.
Your dirty solution is not the worst since you'll know at start how many quizzes you'll have and can allocate the array then.

Get pusherapp members count in channel without counting self

Pusherapp counts yourself when you subscribe to get a members count. Is there any way to not include yourself?
I have a preview view with a members in channel count. If I join the room in another tab I would like that number to go up.
The problem with getting the count, then minus one is that when you actually do join the number won't go up. It also counts other members who are looking at the preview and not where I would actually intentionally subscribe them. Any ideas?
There are 3 possible methods:
You can work out who you are in the members collection by comparing it to the members.me object. See: http://pusher.com/docs/client_api_guide/client_presence_channels#members_me
You can query Pusher's Web API to get a count of users. See:
http://pusher.com/docs/rest_api#method-get-users
Each user will have an ID so you can work out which one is the current user using that.
You could register a Presence WebHook so that your server is notified whenever a user joins or leaves a channel. In this scenario you may need to maintain your own count, but you can get the initial value using method 2, above.
There is no way right now to simply query the members and say "exclude me" as part of that query. So the only solution is to get the full collection (on the client or server) and implement some custom counting logic.

Categories