I would like to be able to publish simultaneously in two directories of my Firebase database. I created a function for this, according to the example proposed in the "Update specific fields" section of the Firebase Javascript documentation:
function linkTwoUsers(user1, user2) {
// The two users are "connected".
var user1Data = {
userLink: user2
};
var user2Data = {
userLink: user1
};
var updates = {};
updates["/users/" + user1] = user1Data;
updates["/users/" + user2] = user2Data;
return database
.ref()
.update(updates)
.then(() => {
return res.status(200).end();
})
.catch(error => {
return res.status(500).send("Error: " + error.message);
});
}
The problem is that when I run the function, instead of uploading the directories, it replaces all the data present in it.
Here are the user directories before the function:
And then:
How do we make sure the data doesn't overwrite the others? Thank you for your help.
Try to narrow your path to just the property you are trying to update:
updates["/users/" + user1 + "/userLink/"] = user1;
updates["/users/" + user2 + "/userLink/"] = user2;
It seems as though you're creating an entirely new object when you set:
var userData = { someThing: stuff }
When you pass that in, it will override the original object. One way you might solve this (there might be a more efficient way) is to grab the objects from Firebase, add the new property and value to the object, then send the entire object back into Firebase.
In some javascript frameworks, you should be able to use the spread operator to set all of an object's props to another object like this:
var newObject = { ...originalObject }
newObject.userData = "something"
// then save newObject to firebase
Related
There are questions on how to update nested properties for a Firebase record, but no answers on how to create records with nested properties.
This and this were similar but did not help.
From the web, the goal is to create a Firebase record with nested properties.
Using dot notation works for updates, but a nested hierarchy doesn't get created when reusing the same key for creating the record.
Which makes sense because the key doesn't impart any information about the data types of the child properties.
What is the right way to create an object with nested properties?
async test(serviceId, numCredits, emailAddress) {
// Set credits key.
let creditsKey = `credits.${serviceId}.numAllowed`;
try {
// Get user matching #emailAddress.
let user = await this.getUser(emailAddress);
// New user? Create database record.
if (!user) {
this.db_
.collection('users')
.add(
{
emailAddress: emailAddress,
[{creditsKey}]: numCredits
}
);
// Nope, user exists so update his/her record.
} else {
// Set update query.
let query = this.db_
.collection('users')
.where('emailAddress', '==', emailAddress);
// Run update query.
const querySnapshot = await query.get();
return querySnapshot.docs[0].ref.update({
[creditsKey]: firebase.firestore.FieldValue.increment(numCredits)
});
}
} catch(e) {
debug('Error in test(): ' + e);
}
}
If I correctly understand your question, the following would do the trick. (There are probably more elegant solutions however...)
const obj = {};
obj.numAllowed = numCredits;
const obj1 = {};
obj1[serviceId] = obj;
// ...
this.db_.collection('users')
.add(
{
emailAddress: emailAddress,
credits: obj1
})
I am trying to update a User in Firebase using Angular 4 with AngularFire2. In the user object that tis saved to the firebase database, I want to insert another object into an array property. In my service I am trying to do this functionality (I already have everything in keys etc also)
generateUserCharacterList(){
this.genCharList = new CharacterList(x, y, z)
this.UserListOfCharacters.push(this.genCharList)
//Other code...
}
This does not work though
The Update specific fields documentation indicated usage of the .update method.
function writeNewPost(uid, username, picture, title, body) {
// A post entry.
var postData = {
author: username,
uid: uid,
body: body,
title: title,
starCount: 0,
authorPic: picture
};
// Get a key for a new Post.
var newPostKey = firebase.database().ref().child('posts').push().key;
// Write the new post's data simultaneously in the posts list and the user's post list.
var updates = {};
updates['/posts/' + newPostKey] = postData;
updates['/user-posts/' + uid + '/' + newPostKey] = postData;
return firebase.database().ref().update(updates);
}
I am considering that you are using the firebase realtime database as compared to the firestore.
You should take the value of the array in a variable, change the value, and then call the update method on the object ref with that new value. Here is the code sample for the explanation:
let userRef = db.object('users/aad1asd123-123asd');
let user = userRef.valueChanges();
let listOfChars = user.listOfChars;
listOfChars.push('a');
listOfChars.push('b');
listOfChars.push('c');
listOfChars.push('d');
userRef.update({listOfChars: listOfChars});
How can I update certain properties of a local storage item or object as new data is inputted throughout the user journey and not lose what was previously entered or if the user decides to update?
My journey of 5 containers consisting of asking the user to input the following:
Name: string
Avatar: integer
Favourite Genres: multiple strings
On the first view I have created the local storage object / item that sets the name within the handleSubmit function.
handleSubmit(event) {
event.preventDefault();
//Profile object
let profile = { 'name': this.state.name, 'avatar': null, 'genres': '' };
// Put the object into storage
localStorage.setItem('profile', JSON.stringify(profile));
// Retrieve the object from storage
var retrievedObject = localStorage.getItem('profile');
//Log object
console.log('retrievedObject: ', JSON.parse(retrievedObject));
//On form submission update view
this.props.history.push('/profile/hello');
}
On my second view I want to update only the avatar property and maintain what the user had inputted in the previous view.
I'm doing this within the handleSelect function like so:
handleSelect(i) {
let selectedAvatarId;
let avatars = this.state.avatars;
avatars = avatars.map((val, index) => {
val.isActive = index === i ? true : false;
return val;
});
this.setState({
selectedAvatarId: selectedAvatarId
})
//Profile object
let profile = { 'avatar': i };
//Update local storage with selected avatar
localStorage.setItem('profile', JSON.stringify(profile));
}
You will need to read the existing value from localStorage, parse it as JSON and then manipulate the data, and write it back. There are numerous libraries out there for easily working with localStorage, but something along the lines of this should work as a generic function:
function updateProfile = (updatedData) => {
const profile = JSON.parse(localStorage.getItem('profile'));
Object.keys(updatedData).forEach((key) => {
profile[key] = updatedData[key];
});
localStorage.setItem('profile', JSON.stringify(profile));
}
If you use object spread, it could look a lot cleaner too:
function updateProfile = (updatedData) => {
const profile = {
...JSON.parse(localStorage.getItem('profile')),
...updatedData
};
localStorage.setItem('profile', JSON.stringify(profile));
}
There should probably be some safety checks in the above code, but hopefully gives you an idea for a starting point.
The only option as far as I know is to get it as a Json, amend accordingly and then save it is again.
So I am doing a project right now requiring the storage of user preferences with JSON. I have searched for a decent amount of time now but can find no solution.For example sake There are three variables user, permissions, serverid . I figured this would work.
tempObject = {
user: []
};
tempObject.user.push({perm:permissions, server:serverid});
Then i would stringify and turn into a JSON. However the output came out like this:
{user[{perm:4, server:883}]}
This was my desperate attempt at grouping the perm and server variables under the indivisuals UserID so further down in the code i can fetch the permissions of each userID. But as you can see it didnt print the user variable, just changed it to an array and took user as a litteral string.
tl;dr
In short i need help being able to have a JSON file be written to where it stores the perm and serverID under the UserID.
Make user an object. Change this:
user: []
for this:
user: {}
and then set the keys like this:
user.perm = 4;
user.server = 883;
For security reasons, client-side JavaScript is not permitted to write to the disk. This sounds like you need a database.
You could leverage localStorage, or perhaps a cookie as an alternate to a database.
I think you should change the users array to an object; that way could key by userID.
for example:
var data = {
users: {}
};
const userID = 1234; // or could be a string like 'john_doe'
const userPermissions = { perm: 4, server: 883 };
// set the user's permissions
data.users[userID] = userPermissions;
// fetching user's permissions
const userData = data.users[userID];
console.log('User ' + userID +' has perm = ' + userData.perm + ' and server = ' + userData.server);
Now saving and loading of this data using local storage is easy:
function saveData() {
localStorage.setItem('UserData', JSON.stringify(data));
}
function loadData() {
data = JSON.parse(localStorage.getItem('UserData'));
}
I'm doing a simple findOne() and saving the doc within it, but for some reason it's not working. I've outputted the object and the output in console is correct, but after the save(), I take a look at my mongodb and it didn't save. I'm not sure if there is some sort of option I'm supposed to set. Here is my code:
var1 = "data1";
var2 = "data1field1";
Model.findOne({'_id':some_id}).exec(function(err, doc) {
if (err) return console.error(err);
(doc.data[var1][var2][0] += 1;
console.log(doc.data.data1);
doc.save(function (err) {
if(err){console.log(err);}
console.log('success');
});
});
Here is my schema:
var modelSchema = new mongoose.Schema({
'data':{
'data1':{
'data1field1':[{type: Number}],
'data1field2':[{type: Number}]
},
'data2':{
'data2field1':[{type: Number}],
'data2field2':[{type: Number}]
}
}
});
var Model = mongoose.model('model', modelSchema);
module.exports.Model = Model;
Say I create an instance of this schema where data.data1.data1field1 is an array of two numbers [0,0], the output for "console.log(doc.data.data1);" would be:
{
data1field1:[1,0],
data1field2:[0,0] }
success
But the save does not happen. I'm new to mongoose/mongodb so there is probably a simple fundamental thing I'm missing.
NOTE: I cannot use Model.update({},{$inc {}}) because I'm using variables to select which data object to change, and because of the literals in .update(), it is impossible.
Thanks.
So mongoose has some smarts to automatically detect changes when you do simple property sets like myModel.name = 'Steve'. However, when you access deeply nested schemas and change properties deep in the graph, the top level document cannot auto-detect this. So you need to tell mongoose what you changed.
doc.markModified('data.' + var1 + '.' + var2);
If you get the correct incantation of that, mongoose will be able to save your change.