How to create a new many to many reference in Javascript? - javascript

Imagine I have one user and one other user. The former would like to follow the latter, which I have designed as a many to many relashionship. How can I do it in Javascript? I need something like user.followers.append(other).

In real life you use database connections for that, and you must have a backend already built. But if you're just playing with objects in JS, then you need a User class with a follow method.
function User (params) => {
const {
name,
age,
friends = []
} = params
this.name = name
this.age = age
this.friends = friends
this.follow = (newFriend) => {
this.friends.append(newFriend)
}
this.showFriends = () => {
console.log(this.friends)
}
}
Then you create two users.
const user = new User({
name: "Joe",
age: 25
})
const other = new User({
name: "Francis",
age: 27
})
Then you make one dude follow the other.
user.follow(other)
Then you can log the user's friends to see what's up.
user.showFriends()

Make user.followers as array. So that you can push the userid of the user who is trying to follow them.
Eg:
user = {'id': 'current_user_id',
'followers' : ['user_id_1', 'user_id_2'....]
};

Related

How to create create a new custom(specific) object and map the data from Array of object

I get a response from backend which is an array of object which is as below mentioned
[{"userID":1,"firstName":"George","lastName":"Russell","addressID":"1","address_value":"27 London Street E146AA","expDate":"2022-12-12T17:09:37.000Z"},{"userID":1,"firstName":"George","lastName":"Russell","phoneId":"1","phone_value":"97627445368"},{"userID":2,"firstName":"George","lastName":"Russell","phoneId":"2","phone_value":"07884076692"},{"userID":1,"firstName":"George","lastName":"Russell","emailId":"1","email_value":"georgerussell#outlook.com"},{"userID":1,"firstName":"George","lastName":"Russell","employerId":"1","employer_value":"QMUL"},{"userID":28,"firstName":"Binny","lastName":"Bansal","employerId":"2","employer_value":"Google Inc"},{"userID":1,"firstName":"George","lastName":"Russell","nationalityId":"1","nationality":"Indian"},{"userID":1,"firstName":"George","lastName":"Russell","passportId":"1","passportNumber":"123445567"}]
I am trying to get all the details of users from the backend which are stored in different tables like a separate table for Phone, Address, Email etc. And similarly for EmailShared or PhoneShared which contains the information regarding with which organisation has the information has been shared. As we can see that HSBC has the address of George.
But what I want to try and do is that have all the information in a single object instead of a different one for each attribute(address, phone, email).
What right now we have is the below one
[
{
addressID: "1"
address_value: "27 London Street E146AA"
expDate: "2022-12-12T17:09:37.000Z"
firstName: "George"
lastName: "Russel"
userID: 1
},
{
firstName: "George"
lastName: "Russel"
phoneId: "1"
phone_value: "97627445368"
userID: 1
}
]
What I am trying to achieve is something which has phone number and address as an example but would love to have all the attributes(phone, email, passport, employer, address etc) .
{
addressID: "1"
address_value: "27 London Street E146AA"
expDate: "2022-12-12T17:09:37.000Z"
firstName: "George"
lastName: "Russel"
userID: 1
phoneId: "1"
phone_value: "97627445368"
emailId:"1",
email_value:"georgerussell#outlook.com"
employerId:"1"
employer_value:"QMUL"
nationalityId:"1"
nationality:"Indian"
passportId:"1"
passportNumber:"123445567"
},
I was trying to do it with the following code as we have the userId as unique property and based on that I was trying to have the desired output but I cannot understand what am I missing in here.
result = data.reduce(function (r, a) {
r[a.userID] = r[a.userID] || [];
r[a.userID].push(a);
return r;
}, Object.create(null));
console.log(result);
const finalResult = [];
Object.keys(result).forEach(el => {
result[el].forEach(el1 => {
console.log(el1)
//finalResult.push(...el1)
})
})
You were on the right track, just needs little improvement like using Object.values() instead of Object.keys(); and I used logical nullish assignment (??=)
const data = [{"userID":1,"firstName":"George","lastName":"Russell","addressID":"1","address_value":"27 London Street E146AA","expDate":"2022-12-12T17:09:37.000Z"},{"userID":1,"firstName":"George","lastName":"Russell","phoneId":"1","phone_value":"97627445368"},{"userID":2,"firstName":"George","lastName":"Russell","phoneId":"2","phone_value":"07884076692"},{"userID":1,"firstName":"George","lastName":"Russell","emailId":"1","email_value":"georgerussell#outlook.com"},{"userID":1,"firstName":"George","lastName":"Russell","employerId":"1","employer_value":"QMUL"},{"userID":28,"firstName":"Binny","lastName":"Bansal","employerId":"2","employer_value":"Google Inc"},{"userID":1,"firstName":"George","lastName":"Russell","nationalityId":"1","nationality":"Indian"},{"userID":1,"firstName":"George","lastName":"Russell","passportId":"1","passportNumber":"123445567"}];
const result = data.reduce(function(r, a) {
r[a.userID] ??= []; // it's the same as r[a.userID] = r[a.userID] || [];
r[a.userID].push({ ...a
});
return r;
}, {}); //Object.create(null)
let finalResult = [];
Object.values(result).forEach((arrObj) => {
let result = {};
Object.values(arrObj).forEach((obj) => {
Object.assign(result, obj);
});
finalResult.push(result);
});
console.log(finalResult);
For this type of problem, I would go with changing how the backend service operates; where it should doing a JOIN on the multiple tables so that you only get one object for each user, instead multiple.
That being said, I would accomplish this easiest with a map.
const result = [{"userID":1,"firstName":"George","lastName":"Russell","addressID":"1","address_value":"27 London Street E146AA","expDate":"2022-12-12T17:09:37.000Z"},{"userID":1,"firstName":"George","lastName":"Russell","phoneId":"1","phone_value":"97627445368"},{"userID":2,"firstName":"George","lastName":"Russell","phoneId":"2","phone_value":"07884076692"},{"userID":1,"firstName":"George","lastName":"Russell","emailId":"1","email_value":"georgerussell#outlook.com"},{"userID":1,"firstName":"George","lastName":"Russell","employerId":"1","employer_value":"QMUL"},{"userID":28,"firstName":"Binny","lastName":"Bansal","employerId":"2","employer_value":"Google Inc"},{"userID":1,"firstName":"George","lastName":"Russell","nationalityId":"1","nationality":"Indian"},{"userID":1,"firstName":"George","lastName":"Russell","passportId":"1","passportNumber":"123445567"}];
const newUserMap = new Map();
result.forEach((user) => {
const { userID } = user;
if (newUserMap.has(userID)) {
const existingUser = newUserMap.get(userID);
newUserMap.set(userID, {...existingUser, ...user});
} else {
newUserMap.set(userID, user);
}
});
console.log(newUserMap);
Where the keys are the user ids and the values within them are the user objects. You are also able to run through each entry with a .forEach() loop; just like an array.
If you want to keep them as an array of objects, then you could accomplish this with something similar to a map, but it is quite costly in performance due to the .findIndex():
const result = [{"userID":1,"firstName":"George","lastName":"Russell","addressID":"1","address_value":"27 London Street E146AA","expDate":"2022-12-12T17:09:37.000Z"},{"userID":1,"firstName":"George","lastName":"Russell","phoneId":"1","phone_value":"97627445368"},{"userID":2,"firstName":"George","lastName":"Russell","phoneId":"2","phone_value":"07884076692"},{"userID":1,"firstName":"George","lastName":"Russell","emailId":"1","email_value":"georgerussell#outlook.com"},{"userID":1,"firstName":"George","lastName":"Russell","employerId":"1","employer_value":"QMUL"},{"userID":28,"firstName":"Binny","lastName":"Bansal","employerId":"2","employer_value":"Google Inc"},{"userID":1,"firstName":"George","lastName":"Russell","nationalityId":"1","nationality":"Indian"},{"userID":1,"firstName":"George","lastName":"Russell","passportId":"1","passportNumber":"123445567"}];
const newUserArray = [];
result.forEach((user) => {
const { userID } = user;
const existingUserIndex = newUserArray.findIndex(newUser => newUser.userID === userID);
if (existingUserIndex !== -1) {
newUserArray[existingUserIndex] = Object.assign(newUserArray[existingUserIndex], user);
} else {
newUserArray.push(user);
}
});
console.log(newUserArray);

Fetch some (and not all) properties from a list in Firebase Realtime Database

Suppose there is a list in my Realtime Database such that it has a user list at location userList as:
user1: { age: 20, name: john }
user2 : { age: 40, name: sam }
user3: { age: 30, name: cynthia }
Is there a way for me to write a query to fetch only the ages from the above userList?
I am currently using Angular 11, and taking help of Angular Fire package to communicate with the Firebase database.
Note: I have removed the apostrophes from the above example for clarity.
There's no direct method to so. You would have to fetch the complete node and then sort it out using Javascript manually. But if you want to fetch just one field then you can try this function which makes separate request for age of each user:
async function getAges() {
const dbRef = firebase.database().ref("users")
const requests = []
const users = ["user1", "user2", "user3"]
for (const user of users) {
requests.push(dbRef.child(user).child("age").once("value"))
}
const snapshots = await Promise.all(requests)
console.log(snapshots.map(snap => `${snap.ref.parent.key} -> ${snap.val()}`))
}
The output in console should be something like this:
Although you would need keys of all nodes i.e. the UIDs of all the users. If you have only UIDs stored somewhere then this method will be useful else to get the keys you need to fetch the complete users node.

How to store an objects in array after method in my class

Please see my code below.
class User {
constructor(name, email) {
this.name = name;
this.email = email;
}
addUser() {
users.push(this.name, this.email)
}
}
const userOne = new User ('John', 'john#mail.com');
const userTwo = new User ("Alan", "alan#mail.com");
let users = [];
userOne.addUser();
userTwo.addUser();
After method addUser i have array with names and emails but i would like to have an array with objects as below
users = [
{ name: 'John', email: 'john#mail.com' }
{ name: 'Alan', email: 'alan#mail.com' }
]
How my method addUser should looks in my prototype and if variable users is in correct place or can be store somewhere in Class?
Thanks in advance
You're pushing the object properties one after the other, rather than as an object together.
Try this for your addUser method:
addUser() {
users.push({name: this.name, email: this.email})
}
You just need to push each proprieties
users.push({name: this.name, email: this.email})
If you want to do this automatically you can use:
users.push(Object.assign({}, this))
Or you cloud just pass the whole object:
users.push(this)
Anyhow, I would suggest not to use users globally.

How does one best group and render items, like with an "interest" property that might be equal amongst many "User" instances?

Hello Everyone I am having some problems trying to make a function. As shown in the code. I want to make the interestMatch function. What the function needs to do is to look at all the Users and find those users that have the same interest - bob and jack in my code. I think it should be something with an if statement. Kinda: "if any users have the same interest" "return this user and this user is a match!"
Can someone help me!?
Thanks a lot!
class User {
constructor(username, password, firstname, lastname, email, birthday, gender, interest){
this.username = username;
this.password = password;
this.firstname = firstname;
this.lastname = lastname;
this.email = email;
this.birthday = birthday;
this.gender = gender;
this.interest = interest
}
}
let InterrestArray = ["Netflix", "Sports", "Party", "Business", "Children", "Hygge"]
let bob = new User ("bob123", "12345", "Bob", "bobiski", "bob#bob.com", "2000-10-10", "male", interrest[0]);
let jack = new User ("jack20", "340302", "Jack", "jackiski", "jack#jack.com", "2000-06-10", "male", interrest[0]);
let thif = new User ("thif20", "204903", "Thifanny", "Thifiski", "thif#jack.com", "2000-09-12", "famale", interrest[1]);
function interestMatch(){
???
}
console.log(interestMatch())
// I want it to console.log - "bob maches with jack!" - because the have the same interrest
```
A very simple approach would be to have two nested for loops which iterate over the users and compares their interest:
function interestMatch(users){
for (let i = 0; i < users.length; i++) {
const user1 = users[i];
// No need to iterate over any user that comes "before" user1.
for (let j = i+1; j < users.length; j++) {
const user2 = users[j];
if (user1.interest === user2.interest) {
return `${user1.username} matches with ${user2.username}`;
}
}
}
}
Of course things get more complex if users can have multiple interests or if you want to return all matches. In that case it might make sense to create an interest -> list of users map.
Any approach the OP is looking for is a little bit more complex than
it should be something with an if statement.
A valid approach was to scan through a list of users, look up each of a user's interest and push the user into its interest related array. Thus the base approach creates an interest based map or index with interest-specific user-lists.
This was just the first part, providing an approach that creates a data structure which can be processed further.
With the needed data structure at hand (a key value store, where interest is key and a specific user-list is each key's value) one approaches the second part which is about output/rendering.
For each key-value pair (interest and user list) one does invoke a user list specific render function. Within this step one also does map the user list into a list of e.g. each of a user's first name.
The final render function then needs to take care of the edge cases ... like ... there is a single user, with an interest which is not shared by anyone else ... or ... there are more than two users who have one and the same interest in common ...
class User {
constructor(
username, password, firstname, lastname,
email, birthday, gender, interest
) {
Object.assign(this, {
username, password, firstname, lastname,
email, birthday, gender, interest
});
}
}
function groupUserByInterest(index, user) {
const { interest } = user;
const sameInterestList = index[interest] || (index[interest] = []);
sameInterestList.push(user);
return index;
}
const interestList = ["Netflix", "Sports", "Party", "Business", "Children", "Hygge"];
const userList = [
new User ("bob123", "12345", "Bob", "bobiski", "bob#bob.com", "2000-10-10", "male", interestList[0]),
new User ("jack20", "340302", "Jack", "jackiski", "jack#jack.com", "2000-06-10", "male", interestList[0]),
new User ("jane20", "340303", "Jane", "janinski", "jane#jane.com", "2000-06-10", "famale", interestList[0]),
new User ("thif20", "204903", "Thifanny", "Thifiski", "thif#jack.com", "2000-09-12", "famale", interestList[1])
];
// const [ bob, jack, jane, thif ] = userList;
function renderUsersOfSameInterest(interest, userList) {
const [ first, ...rest ] = userList;
let template;
if (!rest.length) {
template = `There is no other user who matches ${ first }'s interest (${ interest }).`;
} else {
template = `${ first }'s interest (${ interest }) maches with the one of ${ rest.join(' and ') }!`;
}
console.log(template);
}
function renderUsersOfSameInterestsByFirstname(index) {
Object.entries(index).forEach(([interest, userList]) =>
renderUsersOfSameInterest(interest, userList.map(user =>
user.firstname))
);
// console.log('index', index);
}
renderUsersOfSameInterestsByFirstname(
userList.reduce(groupUserByInterest, {})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

On Firebase, why does remove work on push but not on set?

I'm trying to write on Firebase an object with this structure and when a user reloads or leaves page, the user's data will be removed from Firebase.
/users {
1: {name: name, win: win},
2: {name: name, win: win}
}
This code does that but generates random Id each push so I cannot interfere with each user's data later:
var database = firebase.database();
var userRef = database.ref("/users");
function createNewUser() {
var newUser = $('#newUser').val().trim();
if (newUser) {
var con = userRef.push({
name: newUser,
win: 0,
loss: 0
});
con.onDisconnect().remove();
}
else {
return;
}
}
$('#startButton').on('click', createNewUser);
This code is similar but has error:
onDisconnect is not a function
function createNewUser() {
var newUser = $('#newUser').val().trim();
if (newUser) {
var con = database.ref('users/ + 1).set({
name: newUser,
win: 0,
loss: 0
});
con.onDisconnect().remove();
}
else {
return;
}
}
If I use push, I can retrieve each user's ID but I still won't be able to change user's data, especially if 1 of the 2 users leaves.
When using .push, Firebase will always generate a random key for this new entry.
You can use .set instead of .push and you'll need to add to the path/ref a unique identifier for each user, like userName or userId as userRef.child('/userid').set
Or you can capture the new entry after creation, and get the new generated random key, and then use it for the .remove
See Firebase Documentation here
Hope that helps.
All the best.

Categories

Resources