Save with firebase with a dynamic key name - javascript

I am trying to insert in my database the month chosen by the user.
saveInBdd (){
this.errors = [];
const user = firebase.auth().currentUser;
user.updateProfile({
displayName: this.firstname,
}).then(()=>{
this.saveUserToUsersRef(user)
}, error => {
this.errors.push(error.message)
})
},
saveUserToUsersRef(user){
return this.usersRef.child(user.uid).update({
tab1: { this.months[0].selectedOption : "test"}
})
},
This code returns this error to me:

The property name of a JSON object in the notation you're using needs to be a literal. To use a variable as the name of a property, use [] notation:
saveUserToUsersRef(user){
var updates = {};
updates[this.months[0].selectedOption] = "test";
return this.usersRef.child(user.uid).update(updates))
},

Related

How to change nested JSON value using stringify replacer?

I use JSON.stringify(value, replacer) to mask sensitive data in JSON object.
const inputJsonObject =
{
"id": "uniqueId",
"value": "objectData",
"user": {
"password": "qwerty"
}
};
const hideDataMethod = JSON.stringify(inputJsonObject, (key, value) => {
const dataToHide = ['id', 'user.password'];
return dataToHide.indexOf(key) === -1 ? value : 'xxx';
});
console.log(hideDataMethod);
How to get to user.password value? The above solution works for id but doesn't for password.
It doesn't work for password because you're looking for a property called "user.password", but there is none; the property's name is password, not user.password. (It's a property on an object that's referenced by the user property on another object, but that has nothing to do with the property name.) If you remove the user. part of that, it will work. Beware that doing it removes all id and password properties from all objects in the object graph being stringified:
const inputObject = {
"id": "uniqueId",
"value": "objectData",
"user": {
"password": "qwerty"
}
};
const dataToHide = ["id", "password"];
const json = JSON.stringify(inputObject, (key, value) => {
return dataToHide.indexOf(key) === -1 ? value : "xxx";
});
console.log(json);
(I also changed the name of a couple of variables that had misleading names.)
But I would sanitize it before converting it to JSON rather than during:
const tmp = {
...inputObject,
id: "xxx",
user: {
...inputObject.user,
password: "xxx",
}
};
const json = JSON.stringify(tmp);

Deleting json value with javascript

I have tried to many ways , but i am stuck with a simple function in javascript, and i don't know where i need to looking for ... the problem is this:
I have a Json file like this one:
{
"blacklist": [
{
"email": "strangemail#gmail.com"
},
{
"email": "strangemail1#gmail.com"
},
{
"email": "strangemail2#gmail.com"
},
{
"email": "fianlt#gmail.com"
},
{
"email": "finalstatustest#gmail.com"
}
]
}
I would like simple remove an email with a simple function like this one:
function cancel(email) // parameter that contain the value to delete
{
let rawdata = fs.readFileSync('pvt.json'); //get local json file
let mydata = JSON.parse(rawdata); //parsing rawdata
var key = email; //setting up key
delete mydata.blacklist[key]; //using delete function for delete an element
let data = JSON.stringify(mydata, null, 2); //stringify the result
fs.writeFileSync('pvt.json', data); // overwrite local file with new one with all changes
}
the problem is ... it doesn't works ... i don't know why ... i tried to read the documentation, but i didn't found any solution 😢
The delete operator is for removing a property from an object, using the property's name. You're trying to remove an entry from an array, using the value of a property of an object in the array.
Assuming email is a variable containing the email address in the entry you want to remove, filter is one easy way to do that:
mydata.blacklist = mydata.blacklist.filter(entry => entry.email !== email);
filter builds a new array from the entries in the original array that meet the criteria in the callback — in this case, that their email property doesn't match the email address you want to remove.
If you wanted to modify the array in place rather than creating a new one, you'd use findIndex and splice:
const index = mydata.blacklist.findIndex(entry => entry.email === email);
if (index !== -1) {
mydata.blacklist.splice(index, 1); // Remove the entry at the index
}
Delete works to delete a key-value from an object. Here you have an array of items[objects]. You should use filter to remove unwanted element.
Update:
function cancel(selectedEmail) {
let rawdata = fs.readFileSync("pvt.json"); //get local json file
let mydata = JSON.parse(rawdata); //parsing rawdata
mydata.blacklist = mydata.blacklist.filter(
(item) => item.email !== selectedEmail.email
);
fs.writeFileSync("pvt.json", JSON.stringify(mydata, null, 2)); // overwrite local file with new one with all changes
}
Sample:
const info = {
blacklist: [
{
email: "strangemail#gmail.com",
},
{
email: "strangemail1#gmail.com",
},
{
email: "strangemail2#gmail.com",
},
{
email: "fianlt#gmail.com",
},
{
email: "finalstatustest#gmail.com",
},
],
};
const selectedEmail = {email: "finalstatustest#gmail.com"}
info.blacklist = info.blacklist.filter(item => item.email !== selectedEmail.email)
console.log(info)

Insert and merge a particular field in firestore firebase

I have a doc in my collection in this format
name: xyz,
email: xyz#email.com,
age: 30,
address: {
street_no: {
complete_address: somedata,
pincode: somepin
},
city:somecity,
state:somestate,
landmark:nearby
}
And inside this doc I am trying to insert and merge the complete_address with the previous record. To achieve that I am trying this
const database = firebase.firestore();
var dataRef = database.collection('collection');
var query = dataRef.doc(key+"").get().then(doc=>{
if(!doc.exists){
res.send("doesn't exist");
}else{
//few checks
if(doc.data().accessid != accessid){
res.send("accessid doesn't match")
}
//here I am trying to insert and merge with the previous data
var form_path = 'address.street_no.complete_address';
dataRef.doc(key+"."+form_path).set({
another_address
}, {merge: true});
}
}).catch(err=>{
console.log(err)
})
But when I execute this it just add another document in a collection followed by this path key.address.street_no.complete_address.
What can I do to only insert and merge with the previous complete_address ?
There is . instead of / in form_path because got few ideas from this link
I believe your issue lies within the next couple of lines starting at
var form_path = 'address.street_no.complete_address';
Next, You're using dataRef.doc(key+"."+form_path)
which means the only document being set is
/addressCollection/key.{addressCollectionId}
and addressCollectionId being address.street_no.complete_address
Instead what you want to do is access the property within the document using dot notation like so.
address: {
street_no: {
complete_address
Example.
someDocument.update({
"address.street_no.complete_address": "some_data"
});
Note that "some_data" will replace what ever data is currently stored. You'll want to do one read and merge the data. For example.
const anotherAddress = { address: "123 Fake Street" };
const document = firebase
.firestore()
.collection("addressCollection")
.doc("someAddressId");
document
.get()
.then(snap => {
const data = snap.data();
const completeAddress = data.address.street_no.complete_address };
// We're using the spread operator here to combine the current completeAddress with anotherAddress
return { completeAddress, ...anotherAddress };
})
.then(newCompleteAddress =>
document.update({
"address.street_no.complete_address": newCompleteAddress
})
);
I got this working.
So I figured out what I was trying to do earlier will create another document in a collection with data respect to it. So I start treated everything as an object and passed an object data to set() method.
const database = firebase.firestore();
var dataRef = database.collection('collection');
var query = dataRef.doc(key+"").get().then(doc=>{
if(!doc.exists){
res.send("doesn't exist");
}else{
//few checks
if(doc.data().accessid != accessid){
res.send("accessid doesn't match")
}
//here I am trying to insert and merge with the previous data
var mergeData = {
address : {
}
}
var new_address = {
key: "address_data"
}
mergeData.address[street_no] = {complete_address : address}
if(dataRef.doc(key+"").set(mergeData, {merge: true})){
res.send("done")
}else{
res.send("failed")
}
}
}).catch(err=>{
console.log(err)
})

Mongodb: dynamically exclude fields from update function [duplicate]

I would update a collection setting the value only if the new values are not null.
I have a code like this:
...
var userName = req.body.nome;
var userSurname = req.body.cognome;
var userAddress = req.body.indirizzo;
collection.update(
{_id:ObjectId(req.session.userID)},
{$set: { nome: userName, cognome: userSurname, indirizzo: userAddress }}
)
Is there an easy way for doing this?
ANOTHER WAY:
if I could take the value req.body.* from the placeholder of the form where I take the data, I could solve the problem.. but is this possible?
You could try something like this:
var objForUpdate = {};
if (req.body.nome) objForUpdate.nome = req.body.nome;
if (req.body.cognome) objForUpdate.cognome = req.body.cognome;
if (req.body.indirizzo) objForUpdate.indirizzo = req.body.indirizzo;
//before edit- There is no need for creating a new variable
//var setObj = { $set: objForUpdate }
objForUpdate = { $set: objForUpdate }
collection.update({_id:ObjectId(req.session.userID)}, objForUpdate )
You can use lodash like this other question: https://stackoverflow.com/a/33432857/4777292
_.pickBy({ a: null, b: 1, c: undefined }, _.identity);
would be
{b:1}
Are you not just asking to pass in all the fields that you posted? Why not do this then?
(And basically just a cut and paste of your code):
collection.update(
{_id: ObjectId(req.session.userID)},
{$set: req.body }
)
Then whatever content you posted as fields is set within your update.
Note that use of set will only overwrite, or add new fields. If you just want to replace the whole document, then remove the whole {$set: (..) } notation and just pass in req body as it's a valild object.
You can use mongoose for that by casting req.body to your model,
I assume you have mongoose model called User, and in your controller,
var userModel = new User(req.body);
User.update({_id: req.session.userID}, userModel, {upsert: true}, function(err){
console.log("Error occured!");
});
There is no mongoose tag, but I strongly recomment to use that. For more details;
Mongoose Update
Mongoose Model
If there is not any field that you dont want users to be able to change. since this method will take any value which is not empty and update it. you can do it like this.
const updatedFields = {};
Object.keys(req.body).forEach(key => {
if (!isEmpty(req.body[key])) {
updatedFields[key] = req.body[key];
}
});
YourModel.findOneAndUpdate(
{ employee_id: req.body.employee_id },
{$set:updatedFields},
{new:true}).then(updatedObj =>{
console.log("updated obj:",updatedObj);
})
is empty function
const isEmpty = value =>
value === undefined ||
value === null ||
(typeof value === "object" && Object.keys(value).length === 0) ||
(typeof value === "string" && value.trim().length === 0);
This version still allows for null string fields to be respected and updated. Omitted fields would be ignored.
const cleanedObject = Object.keys(origObject).reduce((acc, k) => {
if (typeof origObject[k] === "undefined") return acc;
acc[k] = origObject[k];
return acc;
}, {});
collection.update({_id:ObjectId(req.session.userID)}, cleanedObject })
Probably you've got already user authenticated so you should have req.user.*
in this case you can use ternary operator to assign the value and update it with either new one or the current one (so there is no update)
var userName = req.body.nome ? req.body.nome : req.user.nome;
var userSurname = req.body.cognome ? req.body.nome : req.user.cognome;
var userAddress = req.body.indirizzo ? req.body.indirizzo : req.user.indirizzo;
collection.update(
{_id:ObjectID(req.session.userID)},
{$set: { nome: userName, cognome: userSurname, indirizzo: userAddress }}
)
If you don't have req.user then you can do it in 3 steps.
1. find user in collection
2. get current data
3. update data with new or current (as above)
let currentName
let currentSurname
db. collection.findOne({_id: ObjectID(req.session.userID)}, (err, user) => {
if (err) { } // handle error here
else if (user) {
currentName = user.name
currentSurname = user.surname
}
})
let objForUpdate = {}
for (const key of Object.keys(req.body)) {
if (req.body[key]) objForUpdate = Object.assign({}, objForUpdate, { [key]: req.body[key] })
}
collection.update({_id:ObjectId(req.session.userID)}, { $set: objForUpdate })
This will dynamically add fields in objForUpdate if defined in the body.
var userName = req.body.nome;
var userSurname = req.body.cognome;
var userAddress = req.body.indirizzo;
collection.update(
{ _id: ObjectId(req.session.userID) },
{
$set: {
...userName && { nome: userName },
...userSurname && { cognome: userSurname },
...userAddress && { indirizzo: userAddress },
},
}
)
The answer by Hüseyin BABAL is on the right track, but that will generate a warning from mongo because calling new User() will create a new _id which is immutable. What you want to do is the following:
const userModel = Object.assign(req.body);
User.update({_id: req.session.userID}, userModel, {upsert: true},
function(err){
console.log("Error occured!");
});

MongoDB, update collection field if new value is not null

I would update a collection setting the value only if the new values are not null.
I have a code like this:
...
var userName = req.body.nome;
var userSurname = req.body.cognome;
var userAddress = req.body.indirizzo;
collection.update(
{_id:ObjectId(req.session.userID)},
{$set: { nome: userName, cognome: userSurname, indirizzo: userAddress }}
)
Is there an easy way for doing this?
ANOTHER WAY:
if I could take the value req.body.* from the placeholder of the form where I take the data, I could solve the problem.. but is this possible?
You could try something like this:
var objForUpdate = {};
if (req.body.nome) objForUpdate.nome = req.body.nome;
if (req.body.cognome) objForUpdate.cognome = req.body.cognome;
if (req.body.indirizzo) objForUpdate.indirizzo = req.body.indirizzo;
//before edit- There is no need for creating a new variable
//var setObj = { $set: objForUpdate }
objForUpdate = { $set: objForUpdate }
collection.update({_id:ObjectId(req.session.userID)}, objForUpdate )
You can use lodash like this other question: https://stackoverflow.com/a/33432857/4777292
_.pickBy({ a: null, b: 1, c: undefined }, _.identity);
would be
{b:1}
Are you not just asking to pass in all the fields that you posted? Why not do this then?
(And basically just a cut and paste of your code):
collection.update(
{_id: ObjectId(req.session.userID)},
{$set: req.body }
)
Then whatever content you posted as fields is set within your update.
Note that use of set will only overwrite, or add new fields. If you just want to replace the whole document, then remove the whole {$set: (..) } notation and just pass in req body as it's a valild object.
You can use mongoose for that by casting req.body to your model,
I assume you have mongoose model called User, and in your controller,
var userModel = new User(req.body);
User.update({_id: req.session.userID}, userModel, {upsert: true}, function(err){
console.log("Error occured!");
});
There is no mongoose tag, but I strongly recomment to use that. For more details;
Mongoose Update
Mongoose Model
If there is not any field that you dont want users to be able to change. since this method will take any value which is not empty and update it. you can do it like this.
const updatedFields = {};
Object.keys(req.body).forEach(key => {
if (!isEmpty(req.body[key])) {
updatedFields[key] = req.body[key];
}
});
YourModel.findOneAndUpdate(
{ employee_id: req.body.employee_id },
{$set:updatedFields},
{new:true}).then(updatedObj =>{
console.log("updated obj:",updatedObj);
})
is empty function
const isEmpty = value =>
value === undefined ||
value === null ||
(typeof value === "object" && Object.keys(value).length === 0) ||
(typeof value === "string" && value.trim().length === 0);
This version still allows for null string fields to be respected and updated. Omitted fields would be ignored.
const cleanedObject = Object.keys(origObject).reduce((acc, k) => {
if (typeof origObject[k] === "undefined") return acc;
acc[k] = origObject[k];
return acc;
}, {});
collection.update({_id:ObjectId(req.session.userID)}, cleanedObject })
Probably you've got already user authenticated so you should have req.user.*
in this case you can use ternary operator to assign the value and update it with either new one or the current one (so there is no update)
var userName = req.body.nome ? req.body.nome : req.user.nome;
var userSurname = req.body.cognome ? req.body.nome : req.user.cognome;
var userAddress = req.body.indirizzo ? req.body.indirizzo : req.user.indirizzo;
collection.update(
{_id:ObjectID(req.session.userID)},
{$set: { nome: userName, cognome: userSurname, indirizzo: userAddress }}
)
If you don't have req.user then you can do it in 3 steps.
1. find user in collection
2. get current data
3. update data with new or current (as above)
let currentName
let currentSurname
db. collection.findOne({_id: ObjectID(req.session.userID)}, (err, user) => {
if (err) { } // handle error here
else if (user) {
currentName = user.name
currentSurname = user.surname
}
})
let objForUpdate = {}
for (const key of Object.keys(req.body)) {
if (req.body[key]) objForUpdate = Object.assign({}, objForUpdate, { [key]: req.body[key] })
}
collection.update({_id:ObjectId(req.session.userID)}, { $set: objForUpdate })
This will dynamically add fields in objForUpdate if defined in the body.
var userName = req.body.nome;
var userSurname = req.body.cognome;
var userAddress = req.body.indirizzo;
collection.update(
{ _id: ObjectId(req.session.userID) },
{
$set: {
...userName && { nome: userName },
...userSurname && { cognome: userSurname },
...userAddress && { indirizzo: userAddress },
},
}
)
The answer by Hüseyin BABAL is on the right track, but that will generate a warning from mongo because calling new User() will create a new _id which is immutable. What you want to do is the following:
const userModel = Object.assign(req.body);
User.update({_id: req.session.userID}, userModel, {upsert: true},
function(err){
console.log("Error occured!");
});

Categories