Insert and merge a particular field in firestore firebase - javascript

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)
})

Related

How to populate an array inside a map function in js and send it to the server?

This is my ObjectIds array -
obj_ids = [
"5ee71cc94be8d0180c1b63db",
"5ee71c884be8d0180c1b63d9",
"5ee71c494be8d0180c1b63d6",
"5ee71bfd4be8d0180c1b63d4"
]
I am using these objectids to serach whether they exist in the db or not and based on that I want to send the response to server.
This is the code I am trying but I dont know how to populate the array and send it to the server.
var msg = [];
obj_ids.map((ele) => {
Lead.find({ _id: ele._id }, async function (error, docs) {
if (docs.length) {
msg.push(
`Lead already exist for Lead id - ${ele._id} assgined to ${docs[0].salesPerson}`
);
} else {
msg.push(`Lead doesn't exist for Lead id: ${ele._id}`);
const newDuty = new AssignedDuty({
duty: ele._id,
salesPerson: req.body.salesPerson,
});
await newDuty.save();
}
});
});
res.json(msg);
By doing this approach I am getting an empty array. I cannot put res.json(msg) inside the loop. If it is possible by using async-await, please guide me through.
You don't need to make multiple queries to find whether given object ids exist in the database.
Using $in operator, you can make one query that will return all the documents where the _id is equal to one of the object id in the list.
const docs = await Lead.find({
_id: {
$in: [
"5ee71cc94be8d0180c1b63db",
"5ee71c884be8d0180c1b63d9",
"5ee71c494be8d0180c1b63d6",
"5ee71bfd4be8d0180c1b63d4"
]
}
});
After this query, you can check which object id is present in the docs array and which is absent.
For details on $in operator, see $in comparison operator
Your code can be simplified as shown below:
const obj_ids = [
"5ee71cc94be8d0180c1b63db",
"5ee71c884be8d0180c1b63d9",
"5ee71c494be8d0180c1b63d6",
"5ee71bfd4be8d0180c1b63d4"
];
const docs = await Lead.find({
_id: { $in: obj_ids }
});
const msg = [];
obj_ids.forEach(async (id) => {
const doc = docs.find(d => d._id == id);
if (doc) {
msg.push(
`Lead already exist for Lead id - ${doc._id} assgined to ${doc.salesPerson}`
);
}
else {
msg.push(`Lead doesn't exist for Lead id: ${id}`);
const newDuty = new AssignedDuty({
duty: id,
salesPerson: req.body.salesPerson
});
await newDuty.save();
}
});
res.json(msg);

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)

Firestore batch update - check if doc exists

I try to update documents using batch. It is OK if they exists but if not I have error. I would like to "set" if doc does not exists
var batch = db.batch();
$.each(newProductsArray, function (key, value) {
if (value['sku']) {
console.log(value['sku']);
var sku = value['sku'];
var name = value['name']
docRef = db_user.collection("products").doc(sku);
batch.update(docRef, {
productSKU: sku + "sku",
productName: name
});
}
});
// Commit the batch
batch.commit().then(function () {
...
)
});
It sounds like you want to use set() instead of update(), telling it to merge fields if the document already exists.
batch.set(docRef, { ... }, { merge: true });

How to add a new key:value pair to existing sub object of a mongoDB document

I am trying to add a new key:value pair to an existing object of mongoDB document, but no steps are helping me
I tried $each, $push $addtoset but i understood those are for arrays then i tried $det but it is updating the existing key:value pair with new key:value pair
Here is my document
{
test:"abc",
test2:"cdf",
test3:{ 1:"one"}
}
if you observer test3 key in the above document i have already 1:"one" now i want to add new key value in the same object
Like
{
test:"abc",
test2:"cdf",
test3:{ 1:"one", 2:"two", 3:"three"}
}
is it possible in mongoDB?
Here is the mongo Query
let val = parseInt(DYNAMICVALUE)
var changfeemaildot = (req.session.email).replace(/\./g, '#')
var seld = {
_id: ObjectId(rx[0]._id)
};
var seldu = {
$set:{
emails: {
[changfeemaildot]: val
}
}
};
var collection =
connection.get().collection('problems');
collection.update(seld, seldu, function (err, rail) {
});
You can use $set. So your code can be something like this
db.collection.update({<your_condition>}, {$set: {"test3.2": "two", "test3.3": "three"}});
In your case, it will be something like this
var seldu = {$set: {["emails." + changfeemaildot]: val}}
You can use $set with findOneAndUpdate. So your code can be something like this
const { Types, connection } = require("mongoose");
const productList = await connection.collection('products').find({}).toArray()
productList.forEach(async function(myDoc) {
await connection.collection('products').
updateOne({ productId: Types.ObjectId(myDoc.productId) }, {
$set: {
productDisplayId: 'anything you want'
}
});
});

Firebase: Update or Create

i am using Firebase and Node.
I would like to use the same method to either update an object, or create it, if for some reason it does not exist.
Consider the following method
const firebaseSave = async function(data) {
const uid = firebase.auth().currentUser.uid
const profilePath = `users/${uid}`
const profileData = {
name: data.name,
}
const userRef = firebaseDb.child(profilePath)
await userRef.set(profileData)
}
What would be the best and correct way to determine if update or set should be called?
thanks
basically with:
"set" you write or replace data to a defined path, like messages/users/
, you can update the information or create it.
Check this out: https://firebase.google.com/docs/database/admin/save-data
I'd say get the data, check if there was something, if there wasn't default to empty object - then update that object.
Something like:
const valueSnapshot = await userRef.once('value');
const userValue = valueShapshot.exists() ? valueShapshot.val() : {};
const profileData = { ...userValue, name: data.name };
await userRef.set(profileData);
That is, assuming you would want to keep the existing data, and merge any new data into it. If you don't care about overwriting anything, no check would be needed at all.
This is my idea, I apply it for the frontend side.
I use the id to identify if we should create or update.
Because on the frontend, usually, new data don't have any id.
In this way, we don't have to check the doc exists or not.
I'm not sure about backend, but it's okay on the frontend.
createOrUpdateTemplate(template: Label): Observable<unknown> {
if (!template.id) {
return from(
this.fs.collection<Label>('templates').add({
...template,
createdAt: firebase.default.firestore.FieldValue.serverTimestamp(),
updatedAt: firebase.default.firestore.FieldValue.serverTimestamp(),
})
);
} else {
return from(
this.fs
.collection<Label>('templates')
.doc(template.id)
.update({
...template,
updatedAt: firebase.default.firestore.FieldValue.serverTimestamp(),
})
);
}
}
await userRef.set(profileData, {merge: true})
You can add {merge: true} which will update the previous document and will create a new document if document do not already exist.

Categories