Can you help me?
I have a problem that I don't know how to solve or why it is happening.
I am consuming an api from nodejs to obtain certain data and as I am obtaining it, I am storing it in Supabase to obtain it, until I form my information object as I need it.
The problem is that when I want to update a table in supabase it throws me the error "All object keys must match", doing some research I found a forum that mentioned that maybe it was because the primary identifier was null, but I made sure by checking data by data . Then according to the PostgreeSQL error code "PGRST102" it is because the body that was sent in the request is not valid.
So my question is why can't I save my array object to my table? What am I doing wrong?
export const summaryActivity = async(req: Request & any, res: Response) => {
let supabase = instanceSupabase();
try {
// get the ID of the organization (important parameter to query data)
const {
data: organization,
error: organizationError
} = await supabase.from('organization').select('id');
const organizationID = organization ? .map(id => id ? .id).toString();
if (!organizationID) {
return res.status(403).json({
error: true,
message: 'ID de la organización indefinido'
});
}
// query between range date
const date_start = req.query.date_start ? moment.utc(req.query.date_start).startOf('day').toDate().toISOString() : moment().toDate().toISOString();
const date_end = req.query.date_end ? moment.utc(req.query.date_end).endOf('day').toDate().toISOString() : moment().toDate().toISOString();
if (!date_start || !date_end) {
return res.status(403).json({
error: true,
message: 'Date Inválid'
});
}
// consulted in API the hours worked of the day
const activitiesDailyURL = process.env.API_BASE_URL + `v2/organizations/${organizationID}/activities/daily?page_limit=300&date[start]=${date_start}&date[stop]=${date_end}`;
const activitiesDailyrequest = await req.app.authClient!.requestResource(activitiesDailyURL, req.app.session);
// convert response to json
const bodyActivitiesDaily = activitiesDailyrequest ? .body;
const convertactivitiesDaily = JSON.parse(bodyActivitiesDaily.toString());
const activitiesDaily: DailyActivityData = convertactivitiesDaily;
if (!activitiesDaily) {
return res.status(403).json({
error: true,
message: 'Something wrong'
});
}
// consulting the Projects table and obtaining the relationship projects x clients
const {
data: projectClients,
error: projectError
} = await supabase.from('projects').select('project_id, name, status, clients ( client_id, name, status )');
if (projectError) {
return res.status(403).json({
error: true,
message: 'Relacion Entidad Proyecto Inválido',
projectError
});
}
// filtering two objects to perform the union of them
const joinProject = activitiesDaily.daily_activities.map(item => {
const obj1Item = projectClients ? .filter(element => item.project_id === element ? .project_id);
return obj1Item ? { ...item,
...obj1Item
} : { ...item
}
});
if (!joinProject) {
res.json("Wrong to join project")
}
// consulting the users table (bring only the DEV, SAC, DESIGN roles)
const {
data: user,
error: userError
} = await supabase.from('user').select('user_id, username, status, daily_hours, rol').in('rol', ['DEV', 'SAC', 'DESIGN']);
if (userError) {
return res.status(403).json({
error: true,
message: 'Relation Entity User Invalid!',
userError
});
}
// filtering user data response with joinProjects to perform the union of them
const joinUser = joinProject ? .map(item => {
const obj1Item = user ? .find(element => item.user_id === element ? .user_id);
return obj1Item ? { ...item,
...obj1Item
} : { ...item
}
});
if (!joinUser) {
return res.status(403).json({
error: true,
message: 'Relation Entity Project Invalid',
userError
});
}
// iterating over the joinUser object to filter data for the same user
let summedTracked = joinUser.reduce((acc, c) => {
let filtered = acc.filter((el: DailyActivityJoin) => el ? .user_id === c ? .user_id);
if (filtered.length > 0) {
acc[acc.indexOf(filtered[0])].tracked += +c.tracked;
acc[acc.indexOf(filtered[0])].overall += +c.overall;
acc[acc.indexOf(filtered[0])].keyboard += +c.keyboard;
acc[acc.indexOf(filtered[0])].input_tracked += +c.input_tracked;
acc[acc.indexOf(filtered[0])].mouse += +c.mouse;
acc[acc.indexOf(filtered[0])].billable += +c.billable;
acc[acc.indexOf(filtered[0])].manual += +c.manual;
acc[acc.indexOf(filtered[0])].idle += +c.idle;
acc[acc.indexOf(filtered[0])].resumed += +c.resumed;
} else {
acc.push(c);
}
return acc;
}, []);
// types of summedTracked
const convertObject: DailyActivityJoin[] = summedTracked;
const newArr: any[] = [];
// map convertObject to create a new array where new items will be passed with the corresponding calculations
convertObject.map(element => {
let range = {
min: 10000,
max: 99999
}
let delta = range.max - range.min
const rand = Math.round(range.min + Math.random() * delta);
const overall = element.overall;
const tracked = element.tracked;
const dayliHours = element.daily_hours
const calculatedActivity = (overall / tracked) * 100;
const totalHoursTracked = (tracked / 3600);
const percentHours = (totalHoursTracked / dayliHours) * 100;
newArr.push({
activityid: rand,
id: element.id,
date: element.date,
user_id: element.user_id,
project_id: element.project_id,
task_id: element.task_id,
keyboard: element.keyboard,
mouse: element.mouse,
overall: element.overall,
tracked: element.tracked,
input_tracked: element.input_tracked,
manual: element.manual,
idle: element.idle,
resumed: element.resumed,
billable: element.billable,
created_at: element.created_at,
updated_at: element.updated_at,
username: element.username,
status: element.status,
daily_hours: element.daily_hours,
rol: element.rol,
"0": element[0],
percentActivity: Math.round(calculatedActivity),
hoursTracked: totalHoursTracked.toFixed(2),
percentHours: Math.round(percentHours),
createRegister: moment().format('YYYY-MM-DD[T]HH:mm:ss.SSS[Z]')
});
});
if (!newArr) {
return res.status(403).json({
error: true,
message: 'Seguimiento de la actividad del usuario indefinido',
userError
});
}
console.log(newArr);
// Find the activity-historic-tracked table within an array of unique ids if they already exist within it
const findId = newArr.map(id => id ? .id);
const {
data: record,
error: errorHistoric
} = await supabase.from('activity-historic-tracked').select('*').in('id', findId)
if (errorHistoric) {
res.json({
error: true,
message: 'Something wrong!',
errorHistoric
})
}
// If it doesn't exist
if (record ? .length !== 0) {
// doSomething...
} else {
// Otherwise update the activity-historic-tracked table
const {
data: historicoActividad,
error: recordError
} = await supabase.from('activity-historic-tracked').upsert(newArr);
if (recordError) {
return res.status(403).json({
error: true,
message: 'Error in upsert',
recordError
});
}
res.status(201).json(historicoActividad);
} catch (error) {
res.status(500).json({
title: 'API Error',
message: 'Internal Server Error'
});
}
}
I also leave you the structure of my table in Supabase
Table
identity primary key historic_id
numerical identification
activity ID int8
date text
user_id int8
project_id int8
task_id int8
int8 keyboard
int8 mouse
traced int8
input_tracked int8
manual int8
idle int8
resume int8
billable int8
text created_in
updated text_in
username text
status text
daily_hours int8
rol text
percentActivity float8
hoursTracked float8
percentHours float8
createregister date
"0" json
Related
I'm a bit confused
I am sending emails with nodemailer, and every time I send one I perform certain validations in order to manage the upload limit of the attachments. If the upload limit exceeds what is established, the service divides that email and sends it in different emails with the same subject and body as well as its attachment.
Every time this happens, it does a _.chunk that takes care of splitting the pdfs array into smaller elements. But, it should be noted that before that, he made a method to prepare the attachments and this is in charge of obtaining certain information from the api to paint the pdf buffer and thus put it in the content of the emails.
But now what I want to do is search within the matrix that performs the step before dividing the files those that are equal to the array that obtains the information and if they are equal, carry out the instruction that it sends
I will explain with a graph:
If getAmount.pdfBuffer === attachmentMap
// doAction console.log('Equals)
But even though I tried to do it, I couldn't, I don't know if it's because for each attachment that the array has divided, it generates a getAmount array. What do you think I'm doing wrong?
async sendEmail(
{
para: to,
asunto: subject,
plantilla: template,
contexto: context,
}: CorreoInfoDto,
attachments: EmailAttachment[],
driveConfig: OAuthGoogleConfig
) {
const totalSize: number = this.getSizeFromAttachments(attachments);
const chunkSplit = Math.floor(isNaN(totalSize) ? 1 : totalSize / this.LIMIT_ATTACHMENTS) + 1;
const attachmentsChunk: any[][] = _.chunk(attachments, chunkSplit);
if ((totalSize > this.LIMIT_ATTACHMENTS) && attachmentsChunk?.length >= 1) {
await Promise.all(
attachmentsChunk?.map(async (attachment: EmailAttachment[], index) => {
console.log('attachment', attachment)
if (this.getSizeFromAttachments(attachment) > this.LIMIT_ATTACHMENTS) {
const result: GenerateDriveLinkResponse[] = await Promise.all(
attachment?.map(item => {
const file = new GoogleDriveUploadFile({
name: item?.filename,
mimeType: MimeTypesEnum.PDF,
body: item?.content
});
return this.uploadFilesService.uploadToDrive(driveConfig, file) as any;
})
)
const texto = result?.map((item, index) => {
console.log('item', item?.webViewLink);
console.log('index', index);
return new SolicitudXLinkDrive({
texto: attachment[index].filename,
link: item?.webViewLink
})
});
context.links = texto;
const link = `(${index + 1}/${attachmentsChunk?.length - 1})`;
const newContext = {
getCurrent: link,
...context
}
const prepareEmail = this.prepareEmail({
para: to,
asunto: ` ${subject} (${index + 1}/${attachmentsChunk?.length})`,
plantilla: template,
contexto: newContext,
}, []);
return prepareEmail
} else {
// this.getCantidad = `(${index + 1}/${attachmentsChunk?.length - 1})`;
console.log('getCantidad', this.getAmount );
const attachmentMap = attachment.map(element => element.content);
this.getAmount .forEach(element => {
if (element.pdfBuffer === attachmentMap) {
console.log('do action');
}
})
const link = ` (${index + 1}/${attachmentsChunk?.length - 1})`;
const newContext = {
getCurrent: link,
...context
}
return this.prepareEmail({
para: to,
asunto: ` ${subject} (Correo ${index + 1}/${attachmentsChunk?.length - 1})`,
plantilla: template,
contexto: newContext,
}, attachment);
}
})
);
} else {
await this.prepareEmail(
{
para: to,
asunto: ` ${subject}`,
plantilla: template,
contexto: context,
},
attachments,
);
}
}
async prepareEmail(
{
para: to,
asunto: subject,
plantilla: template,
contexto: context,
}: CorreoInfoDto,
attachments: EmailAttachment[],
) {
return await this.mailerService.sendMail({
to,
from: `${process.env.SENDER_NAME} <${process.env.EMAIL_USER}>`,
subject,
template,
attachments: attachments,
context: context,
});
}
async sendEmails(correos: EnvioMultiplesCorreosDto) {
let pdf = null;
let info: ConfiguracionDocument = null;
let GDriveConfig: ConfiguracionDocument = null;
let logo: ConfiguracionDocument = null;
let forContext = {};
const documents = Array.isArray(correos.documento_id) ? correos.documento_id : [correos.documento_id];
const solicitudes = await this.solicitudesService.findByIds(documents);
const nombresPacientes = solicitudes.reduce((acc, cv) => {
acc[cv.correlativo_solicitud] = cv['info_paciente']?.nombre_paciente;
return acc;
}, {});
await Promise.all([
await this.getPdf(correos.tipo_reporte, correos.documento_id, correos?.dividir_archivos).then(data => { pdf = data; }),
await this.configuracionesService.findByCodes([
ConfigKeys.TEXTO_CORREO_MUESTRA,
ConfigKeys[process.env.DRIVE_CONFIG_API],
ConfigKeys.LOGO_FIRMA_PATMED
]).then(data => {
info = data[0];
GDriveConfig = data[1];
logo = data[2];
})
]);
forContext = this.configuracionesService.castValorObjectToObject(info?.valor_object)
const attachmentPrepare = this.prepareAttachments(pdf as any, nombresPacientes);
await this.sendEmail(
{
para: correos.para,
asunto: correos.asunto,
plantilla: 'muestras',
contexto: {
cuerpo: correos.cuerpo,
titulo: forContext[EnvioCorreoMuestraEnum.titulo],
direccion: forContext[EnvioCorreoMuestraEnum.direccion],
movil: forContext[EnvioCorreoMuestraEnum.movil],
pbx: forContext[EnvioCorreoMuestraEnum.pbx],
email: forContext[EnvioCorreoMuestraEnum.email],
logo: logo?.valor,
},
},
attachmentPrepare,
this.configuracionesService.castValorObjectToObject(GDriveConfig?.valor_object) as any,
);
const usuario = new UsuarioBitacoraSolicitudTDTO();
usuario.createFromUserRequest(this.sharedService.getUserFromRequest());
solicitudes.forEach((solicitud) => {
const actual = new BitacoraSolicitudDTO();
actual.createFromSolicitudDocument(solicitud);
const newBitacora = new CrearBitacoraSolicitudDTO();
newBitacora.createNewItem(null, actual, actual, usuario, AccionesBitacora.EmailEnviado);
this.bitacoraSolicitudesService.create(newBitacora);
});
}
prepareAttachments(item: BufferCorrelativosDTO | BufferXSolicitudDTO[], nombresPacientes: { [key: string]: string }) {
if (this.sharedService.isAnArray(item)) {
const castItem: BufferXSolicitudDTO[] = item as any;
this.getCantidad = castItem;
return castItem?.map((s) => {
const namePatient = nombresPacientes[s.correlativo_solicitud];
return new EmailAttachment().setFromBufferXSolicitudDTO(s, namePatient, 'pdf');
});
} else {
return [new EmailAttachment().setFromBufferCorrelativosDTO(item as any, 'pdf')];
}
}
Thank you very much for your attention, I appreciate it. Cheers
You could try using lodash as this has _.intersectionBy and _.intersectionWith functions that should allow you to compare 2 arrays and filter the common values.
There are some good examples here:
How to get intersection with lodash?
Good Evening,
I am using the MERN stack to create an application. I am using the Stripe API to gather invoices and save some information about the invoice in MongoDB. Right now I have a function that updates my DB with any object that does not exist and I have a delete function that deletes any documents in my DB that have the paid: true. when an invoice is paid Stripe marks it paid, when its paid I want to delete it from my DB. What happens now is that I delete it and then update function runs and just puts it right back.
The data in my DB and from stripe are an array of objects:
DB Sample:
[
{
Id: String,
created: Number,
customer_email: String,
customer_name: String,
due_date: Number,
hosted_invoice_url: String,
paid: Boolean
}
]
Codebase functions:
// Update and store function
async function saveInvoice(stripeInvoice) {
const condition = {id: stripeInvoice.id};
const query = {
id: stripeInvoice.id,
created: stripeInvoice.created,
customer_email: stripeInvoice.customer_email,
customer_name: stripeInvoice.customer_name,
due_date: stripeInvoice.due_date,
hosted_invoice_url: stripeInvoice.hosted_invoice_url,
paid: stripeInvoice.paid,
};
const options = { upsert: true };
const update = await InvoiceModel.updateMany(condition, query, options).catch((e) => {console.log(e)});
if(update.nModified > 0 ) {
console.log('Number of Invoices added or updated to DB:', update.nModified)
}
}
// Find common ID
function findCommoneID(stripeInvoice, DBInvoices) {
var isSame = true;
if(DBInvoices.length <= 0 || stripeInvoice.length <= 0) {
console.log('An Error has occured with Database or Stripe Data')
return isSame = false;
} else {
stripeInvoice.forEach((StripeElement) => {
DBInvoices.forEach((DBElement) => {
if(StripeElement.id !== DBElement.id) {
saveInvoice(StripeElement, DBElement);
isSame = false;
}
})
});
}
console.log('IDS match')
return isSame;
}
// Delete Function
async function deletePaidInvoicesFromDB(dbInvoices) {
for(let i = 0; i < dbInvoices.length; i++) {
if(dbInvoices[i].paid === true ) {
console.log(dbInvoices[i].id);
const deletedInvoices = await InvoiceModel.deleteMany({paid: true});
console.log(deletedInvoices.deletedCount)
break;
}
}
}
The save function takes in the data gathered from the findCommonId() function and if the id doesn't exist it adds the stripe object to the DB.
// Save Function
async function saveInvoice(stripeInvoice) {
if(stripeInvoice.paid === true) {
return;
} else {
const condition = {id: stripeInvoice.id};
const query = {
id: stripeInvoice.id,
amount_due: stripeInvoice.amount_due,
created: stripeInvoice.created,
customer_email: stripeInvoice.customer_email,
customer_name: stripeInvoice.customer_name,
due_date: stripeInvoice.due_date,
hosted_invoice_url: stripeInvoice.hosted_invoice_url,
paid: stripeInvoice.paid,
};
const options = { upsert: true };
const update = await InvoiceModel.updateMany(condition, query, options).catch((e) => {console.log(e)});
if(update.nModified > 0 ) {
console.log('Number of Invoices added or updated to DB:', update.nModified)
}
}
}
// findCommoneId
function findCommoneID(stripeInvoice, DBInvoices) {
if(DBInvoices.length <= 0 || stripeInvoice.length <= 0) {
InvoiceModel.create(stripeInvoice, () => {console.log('Invoices saved to database')});
console.log('An Error has occured with Database or Stripe Data')
stripeInvoice.forEach((StripeElement) => {
if(StripeElement.paid === true) {
return;
}
})
stripeInvoice.forEach((StripeElement) => {
DBInvoices.forEach((DBElement) => {
if(StripeElement.id !== DBElement.id) {
saveInvoice(StripeElement);
}
})
});
}
console.log('IDS match')
}
For certain types of messages, I want to target users by FIRTokens vs topic, which are stored in my real-time database. I load these tokens with async/await and then decide if I want to send notifications to a topic vs a smaller list of users. The data loading code works as expected. But what's odd is that if I use .sendMulticast(payload), the notifications fail for all tokens in the list. On the other hand if I use .sendToDevice(adminFIRTokens, payload) the notification goes successfully to all my users. Right now my list has 2 tokens and with sendMulticast I have 2 failures and with sendToDevice I have 2 successes. Am I missing the point of what sendMulticast is supposed to do? According to the docs: Send messages to multiple devices:
The REST API and the Admin FCM APIs allow you to multicast a message to a list of device registration tokens. You can specify up to 500 device registration tokens per invocation.
So both should logically work. Then why does one fail and the other work? In fact with sendToDevice I get a multicastId in the response!
Here are some console outputs:
sendToDevice:
Sent filtered message notification successfully:
{
results:
[
{ messageId: '0:1...45' },
{ messageId: '16...55' }
],
canonicalRegistrationTokenCount: 0,
failureCount: 0,
successCount: 2,
multicastId: 3008...7000
}
sendMulticast:
List of tokens that caused failures: dJP03n-RC_Y:...MvPkTbuV,fDo1S8jPbCM:...2YETyXef
Cloud function to send the notification:
functions.database
.ref("/discussionMessages/{autoId}/")
.onCreate(async (snapshot, context) => {
// console.log("Snapshot: ", snapshot);
try {
const groupsRef = admin.database().ref("people/groups");
const adminUsersRef = groupsRef.child("admin");
const filteredUsersRef = groupsRef.child("filtered");
const filteredUsersSnapshot = await filteredUsersRef.once("value");
const adminUsersSnapshot = await adminUsersRef.once("value");
var adminUsersFIRTokens = {};
var filteredUsersFIRTokens = {};
if (filteredUsersSnapshot.exists()) {
filteredUsersFIRTokens = filteredUsersSnapshot.val();
}
if (adminUsersSnapshot.exists()) {
adminUsersFIRTokens = adminUsersSnapshot.val();
}
const topicName = "SpeechDrillDiscussions";
const message = snapshot.val();
const senderName = message.userName;
const senderCountry = message.userCountryEmoji;
const title = senderName + " " + senderCountry;
const messageText = message.message;
const messageTimestamp = message.messageTimestamp.toString();
const messageID = message.hasOwnProperty("messageID")
? message.messageID
: undefined;
const senderEmailId = message.userEmailAddress;
const senderUserName = getUserNameFromEmail(senderEmailId);
const isSenderFiltered = filteredUsersFIRTokens.hasOwnProperty(
senderUserName
);
var payload = {
notification: {
title: title,
body: messageText,
sound: "default",
},
data: {
messageID: messageID,
messageTimestamp: messageTimestamp,
},
};
if (isSenderFiltered) {
adminFIRTokens = Object.values(adminUsersFIRTokens);
// payload.tokens = adminFIRTokens; //Needed for sendMulticast
return (
admin
.messaging()
.sendToDevice(adminFIRTokens, payload)
// .sendMulticast(payload)
.then(function (response) {
if (response.failureCount === 0) {
console.log(
"Sent filtered message notification successfully:",
response
);
} else {
console.log(
"Sending filtered message notification failed for some tokens:",
response
);
}
// if (response.failureCount > 0) {
// const failedTokens = [];
// response.responses.forEach((resp, idx) => {
// if (!resp.success) {
// failedTokens.push(adminFIRTokens[idx]);
// }
// });
// console.log(
// "List of tokens that caused failures: " + failedTokens
// );
// }
return true;
})
);
} else {
payload.topic = topicName;
return admin
.messaging()
.send(payload)
.then(function (response) {
console.log("Notification sent successfully:", response);
return true;
});
}
} catch (error) {
console.log("Notification sent failed:", error);
return false;
}
});
I think it's an issue of using a different payload structure.
This is the old one (without iOS specific info):
var payload = {
notification: {
title: title,
body: messageText,
sound: "default",
},
data: {
messageID: messageID,
messageTimestamp: messageTimestamp,
},
};
Whereas this is the new version (apns has iOS specific info)
var payload = {
notification: {
title: title,
body: messageText,
},
data: {
messageID: messageID,
messageTimestamp: messageTimestamp,
},
apns: {
payload: {
aps: {
sound: "default",
},
},
},
};
With the new structure, both send and sendMulticast are working properly. Which would fail to send or give errors like apns key is not supported in payload.
The new function:
functions.database
.ref("/discussionMessages/{autoId}/")
.onCreate(async (snapshot, context) => {
// console.log("Snapshot: ", snapshot);
try {
const groupsRef = admin.database().ref("people/groups");
const adminUsersRef = groupsRef.child("admin");
const filteredUsersRef = groupsRef.child("filtered");
const filteredUsersSnapshot = await filteredUsersRef.once("value");
const adminUsersSnapshot = await adminUsersRef.once("value");
var adminUsersFIRTokens = {};
var filteredUsersFIRTokens = {};
if (filteredUsersSnapshot.exists()) {
filteredUsersFIRTokens = filteredUsersSnapshot.val();
}
if (adminUsersSnapshot.exists()) {
adminUsersFIRTokens = adminUsersSnapshot.val();
}
// console.log(
// "Admin and Filtered Users: ",
// adminUsersFIRTokens,
// " ",
// filteredUsersFIRTokens
// );
const topicName = "SpeechDrillDiscussions";
const message = snapshot.val();
// console.log("Received new message: ", message);
const senderName = message.userName;
const senderCountry = message.userCountryEmoji;
const title = senderName + " " + senderCountry;
const messageText = message.message;
const messageTimestamp = message.messageTimestamp.toString();
const messageID = message.hasOwnProperty("messageID")
? message.messageID
: undefined;
const senderEmailId = message.userEmailAddress;
const senderUserName = getUserNameFromEmail(senderEmailId);
const isSenderFiltered = filteredUsersFIRTokens.hasOwnProperty(
senderUserName
);
console.log(
"Will attempt to send notification for message with message id: ",
messageID
);
var payload = {
notification: {
title: title,
body: messageText,
},
data: {
messageID: messageID,
messageTimestamp: messageTimestamp,
},
apns: {
payload: {
aps: {
sound: "default",
},
},
},
};
console.log("Is sender filtered? ", isSenderFiltered);
if (isSenderFiltered) {
adminFIRTokens = Object.values(adminUsersFIRTokens);
console.log("Sending filtered notification with sendMulticast()");
payload.tokens = adminFIRTokens; //Needed for sendMulticast
return admin
.messaging()
.sendMulticast(payload)
.then((response) => {
console.log(
"Sent filtered message (using sendMulticast) notification: ",
JSON.stringify(response)
);
if (response.failureCount > 0) {
const failedTokens = [];
response.responses.forEach((resp, idx) => {
if (!resp.success) {
failedTokens.push(adminFIRTokens[idx]);
}
});
console.log(
"List of tokens that caused failures: " + failedTokens
);
}
return true;
});
} else {
console.log("Sending topic message with send()");
payload.topic = topicName;
return admin
.messaging()
.send(payload)
.then((response) => {
console.log(
"Sent topic message (using send) notification: ",
JSON.stringify(response)
);
return true;
});
}
} catch (error) {
console.log("Notification sent failed:", error);
return false;
}
});
I want to get the Key generated when I push data to Firebase database. I want to handle them with my own function,
So the issue is when the user fills the form he sends the data to our real-time DB, contained in this data are some images (optional), and I don't need to let the image object empty in DB, so how to handle this, and when the user needs to send an image I want to save this image in the same Order, not in New Order.
Node
Here is my function
handleOrder = () => {
const { nameOfProblem, description, userId, imageOfPrblem, providerId } = this.state;
const PushData = firebase.database().ref("request/" + providerId + "/" + userId + "/orders/");
const ref = firebase.storage().ref("users/" + userId + "/UserImageOrders/" + path);
let file = imageOfPrblem.uri;
const path = "img_" + imageOfPrblem.fileName;
var newOrderRef = PushData.push({
nameOfProblem: nameOfProblem,
description: description,
});
if (file) {
let keyG = newOrderRef.key; // Key Generated with .push()
PushData.child(keyG).update({ // didn't updated the key generated just add new element with new key !!
imageOfPrblem: imageOfPrblem
});
ref.put(file).then(() => {
console.log("File uploaded..")
});
}
}
handleImages = () => {
const options = {
title: "Select Images!",
storageOptions: {
skipBackup: true,
path: "images"
}
};
ImagePicker.showImagePicker(options, response => {
console.log("Response = ", response);
if (response.uri) {
this.setState({ imageOfPrblem: response });
}
if (response.didCancel) {
console.log("User cancelled image picker");
} else if (response.error) {
console.log("ImagePicker Error: ", response.error);
} else if (response.customButton) {
console.log("User tapped custom button: ", response.customButton);
alert(response.customButton);
}
});
};
This seems to work fine for me:
var ref = firebase.database().ref("/55912103");
var newChildRef = ref.push({ firstChild: true });
console.log("new key: "+newChildRef.key);
ref.child(newChildRef.key).update({ secondChild: true });
After running this code, I end up with this JSON in the new child whose key gets logged:
"-LdgLWu_wBNNicFlPDGj" : {
"firstChild" : true,
"secondChild" : true
}
Live demo: https://jsbin.com/hovoleh/edit?js,console
Live JSON: https://stackoverflow.firebaseio.com/55912103.json?print=pretty
Update: if you just want to write both the existing data and new data to a new location:
var newOrderRef = PushData.push({
nameOfProblem: nameOfProblem,
description: description,
});
if (file) {
let keyG = newOrderRef.key; // Key Generated with .push()
PushData.child(keyG).update({
nameOfProblem: nameOfProblem,
description: description,
imageOfPrblem: imageOfPrblem
});
ref.put(file).then(() => {
console.log("File uploaded..")
});
}
The push ID from any Firebase snapshot ref is in ref.name().
I know it's been a while since the author created a post but maybe someone will find it useful.
The above answers are a bit wrong because, for example, after: newChildRef
var ref = firebase.database().ref("/55912103");
var newChildRef = ref.push({ firstChild: true });
newChildRef <--- promise
ref = rdb.ref('name_of_your_ref');
var childRef = ref.push({
IdUser: currentUserId,
ProductCategory: pCategory,
ProductDescription: pDesc,
ProductId: pId,
ProductName: pName,
ProductPrice: pPrice,
ProductQuantity: pQuan
}).catch(err => console.log(err.message));
childRef.then(item => {
ref.child(item.key).update({
IdKey: item.key
}).then(() => history.push('/delivery/basket'));
});
Greetings, Matthew
I want to search for multiple words using this query below. when i search for 'document role' I should get all documents that have all document and all document that has role in it using sequelize
function searchDocuments(req, res) {
const limit = req.query.limit || 6,
offset = req.query.offset || 0,
queryString = req.query.q,
splitString = queryString.split(' ');
let querySearch = '';
splitString.forEach((query, index, initial) => {
console.log(initial[index]);
});
if (!queryString) {
return res.status(400).json({
message: 'Invalid search input'
});
}
if (req.decoded.roleId === 1) {
return Document.findAndCountAll({
limit,
offset,
where: {
title: {
$iLike: `%${querySearch}%`
}
},
include: [
{
model: User,
attributes: ['userName', 'roleId']
}
]
})
.then(({ rows: document, count }) => {
if (count === 0) {
return res.status(404).json({
message: 'Search term does not match any document.'
});
}
res.status(200).send({
document,
pagination: pagination(count, limit, offset),
});
})
.catch(error => res.status(400).send(error));
I just want a sequelize query that perform does an OR task with the keyword of title
From the top add the following code:
const limit = req.query.limit || 6,
offset = req.query.offset || 0,
queryString = req.query.q.replace(/ +(?= )/g, ''),
searchQuery = [];
if (!queryString) {
return res.status(400).json({
message: 'Invalid search input'
});
}
if (req.decoded.roleId === 1) {
const splitString = queryString.trim().split(' ');
splitString.forEach((query) => {
const output = { $iLike: `%${query}%` };
searchQuery.push(output);
});
Then add the following where you are querying searchQuery:
where: {
title: {
$or: searchQuery
}
}