Can't update my table in SQLite using express.js - javascript

I am trying to update few records in table in database but I got FOREIGN KEY constraint failed every time I try. Connection works fine because I tried to post new records and it worked without problems.
This is my backend code:
module.exports = function (server, db) {
// function to insert object to db
function insertTickets(ticket) {
const stmt = db.prepare(
"UPDATE tickets SET userid=?, concertid=?, booked=? WHERE ticketid=?"
);
stmt.run(ticket.ticketid, ticket.userid, ticket.concertid, ticket.booked);
console.log(stmt);
}
server.put("/data/tickets", (request, response) => {
const tickets = request.body;
console.log(request.body);
try {
tickets.forEach((ticket) => {
insertTickets(ticket);
});
response.send("tickets inserted to database");
} catch (e) {
console.error(e);
}
});
};
Data I am trying to update is an array with objects:
const tickets = [
{ticketid: 1, userid: 1, concertid: 1, booked: 1},
{ticketid: 3, userid: 1, concertid: 1, booked: 1}]
Interesting part is, first record is updated only when i try to update two.
UPDATE:
problem solved. I deleted concertid=? and concert parameter.

Related

MongoDB: Error “Cannot use a session that has ended” when inserting into a collection

Started using mongoDB today and used the sample code to first connect to a existing database and then add a new object into my collection:
//jshint esversion:6
const { MongoClient } = require("mongodb");
// Replace the uri string with your connection string.
const uri =
"mongodb://localhost:27017";
const client = new MongoClient(uri);
async function run() {
try {
const database = client.db('shopDB');
const products = database.collection('products');
// Query for a movie that has the title 'Back to the Future'
const query = { id: 1 };
const product = await products.findOne(query);
console.log(product);
//insert a new products
var newProduct = {id: 5, name: 'Cat', price: 10, stock: 0};
products.insertOne(newProduct, async function(err, res){
if (err) throw err;
console.log('1 product created');
})
} finally {
await client.close();
}
}
run().catch(console.dir);
If I execut the above code I get: Error “Cannot use a session that has ended” when inserting into a collection I assume it is because of the await client.close(); because if add this command to the callback func of my insertOne() func it works fine.
But if the command is in finally shouldn't the connection be terminated at the end of the function run()? Why is the session ended before I could insert my object?
Thank you for your help!
You are not awaiting for the insert and you code goes straight to finally to close the connection before the insert executes
await products.insertOne(newProduct)

Pass one of three stripe price IDs to server for creating user session

I have three different product IDs for my subscription app but can't figure out how to have the server redirect to the proper customer session based on which price ID is passed from the client side.
The three price ids work (I've checked each individually) and are coming from my .env file -- they're saved as below:
const { webUrl, stripeSecret, stripeWebhookSecret, basicPriceId, scaledPriceId } = require('../production');
Controller function - help needed under the line_items array for price
module.exports.createCheckoutSession = async (req, res) => {
const { currency } = req.body;
if (req.isAuthenticated()) {
if (!(req.user.stripe_customer && req.user.stripe_customer[currency])) {
const new_stripe_customer = await stripe.customers.create({
email: req.user.email,
name: req.user.username,
metadata: {
user_id: req.user._id.toString(),
},
});
let update = {};
update[`stripe_customer.${currency}`] = new_stripe_customer.id;
update['customer_name'] = new_stripe_customer.name;
await User.findByIdAndUpdate(req.user._id, update);
if (!req.user.stripe_customer) {
req.user.stripe_customer = {};
req.user.stripe_customer[currency] = new_stripe_customer.id;
} else {
req.user.stripe_customer[currency] = new_stripe_customer.id;
}
const user = await User.findById(req.user.id);
user.stripeId = new_stripe_customer.id;
await user.save();
}
try {
const session = await stripe.checkout.sessions.create({
mode: "subscription",
customer: req.user.stripe_customer[currency],
line_items: [
{
// where I need help
price: { basicPriceId, scaledPriceId, enterprisePriceId },
quantity: 1,
},
],
success_url: `${webUrl}/users/${req.user._id}/activations/?session_id= {CHECKOUT_SESSION_ID}`,
cancel_url: `${webUrl}/canceled.html`,
});
return res.redirect(303, session.url);
} catch (e) {
res.status(400);
return res.send({
error: {
message: e.message,
}
});
}
}
req.flash('error', "You must login before changing billing");
res.render('/login');
}
With the three price id variables listed in the price row, I receive {"error":{"message":"enterprisePriceId is not defined"}}.
However, the ids are properly being passed from client to server so if I switch the row from all three variables listed to only one of the variables listed it works just fine:
Doesn't work
price: { basicPriceId, scaledPriceId, enterprisePriceId },
Works
price: basicPriceId,
How do I structure the controller code so the user can choose between the three different prices and be redirected to the proper payment checkout page?
You should check which one is present before making the Checkout Session call, and pass the proper value in. The Checkout Session Creation API expects a valid value.

how to correctly update all data in the Mongodb via updateMany?

const filterId = await this.extractValue(query, 'id');
const activeChange = await this.productModel.updateMany(
{ _id: filterId },
{ $set: { active: false} },
);
this method updates one record by id, i need it to get an array of objects and update the whole Mongodb database with them, tell me how to implement this? thanks in advance

Mongoose updateOne() going through okay but not updating

I have this request:
// PUT that updates a user.
router.put('/api/user/:id', async (req: Request, res: Response) => {
const { email, name, avatar } = req.body
const userId = req.body._id
const conditions = {
_id : userId
}
const user = {$set: { "email": email, "name": name, "avatar": avatar } }
User.updateOne(conditions, user).then(doc => {
if (!doc) { return res.status(404).end() }
return res.status(200).json(doc)
}).catch(error => console.log(error))
})
And I get this response from the request:
{
"n": 0,
"nModified": 0,
"ok": 1
}
If you can find it on StackOverflow about the updateOne() method in mongoose I've probably tried it. The document isn't updating no matter what I try.
Edit: I've tried using an ObjectID in the query instead and the same result.
Edit 2: I figured it out. Was using req.body.id instead of req.params.id and I was using parameters to send the request. Thanks everyone for the help!
nModified == 0 implies that you have no user matching this id,
your route is put /api/user/:id but your user id is in req.params.id and not in req.body._id
A couple tips:
Try running the same query from mongodb at the command line, see if you get any results.
Is the "campaign_id" defined as an ObjectId in your schema? If so, try searching using the ObjectId type.
Try to change the query to :
const ObjectId = require('mongoose').Types.ObjectId;
const conditions = {
_id : new ObjectId(userId)
}
The reason for not updating is - mongoose is unable to search the with the id you provided.
if you want to update a document based on _id you can use findByIdAndUpdate()
const userId = req.body._id;
const user = { "email": email, "name": name, "avatar": avatar }
User.findByIdAndUpdate(userId , user,
function (err, docs) {
if (err){
console.log(err)
}
else{
console.log("Updated User : ", docs);
}
});
In case you've set your DB to strict mode don't forget to add strict:false in options when adding new keys. Otherwise, inserts will be silently ignored. I've just spent 2 hours wondering why my inserts don't get saved in DB despite not throwing any error.
See dos
http://mongoosejs.com/docs/guide.html#strict
const conditions = {
_id
}
const dateToUpdate = {
$set: {
"email": "email",
"name": "name",
"avatar": "avatar"
}
}
const updateRecord = await models.pdDealModel.updateOne(conditions,dateToUpdate,{
upsert:false,
strict:false
}
)

How do I query Firebase using Typescript?

I have push notifications set up for my app using Firebase Cloud Functions. It works well. Now I want to update the app's badge count as part of the push notification. I've read that the only way to do that is via server-side code; I can't do it locally.
So I'm trying to get the number of new users from the server and then use that number as the badge count when I send the push notification, but I can't figure out how to go about it. I've spent three days on this and now I'm hoping someone can point me in the right direction.
I'm using Firebase functions and Typescript (with VSCode). My course of action is to:
get list of userIDs from 'admin' node
iterate over those userIDs on 'user' node to query if user's 'newUser' parameter is true
append those results to an array
count the array and then send that to the badge on push notification
My 'users' database structure is like so:
"users": {
"2NBvNgdNRVe3nccTEDts2Xseboma": {
"email": "someone#someone.com"
"newUser": "true",
"referral": "none",
...
},
"hjC6os6wzIV1FyULmGxalU3fM7ef": {
"email": "someoneElse#someone.com"
"newUser": "false",
"referral": "Bennett",
...
}
And my 'admin' database is structured like so:
"admin": {
"2NBvNgdNRVe3nccTEDts2Xseboma": {
"email": "someone#someone.com"
"familyName": "Someone",
"memberSince": "1529119893",
},
"hjC6os6wzIV1FyULmGxalU3fM7ef": {
"email": "someoneElse#someone.com"
"familyName": "Someone Else",
"memberSince": "1529125722",
...
}
Here is my feeble attempt to code this:
exports.getNewUserCount =
functions.database.ref('/users/{userID}/newUser')
.onUpdate((snapshot, _context) => {
console.log('test 2')
// Get a database reference
const db = admin.database();
const ref = db.ref('admin');
return ref.once('value', function(adminSnap) {
const userData = adminSnap.val()
console.log('admin key:', adminSnap.key)
console.log('user data:', userData)
})
});
Right now I'm stuck on retrieving the list of users from the admin node (my step #1 above).
UPDATE
I finally got a list of the users as a snapshot, but I can't figure out how to iterate over them. How do I turn the snapshot into an array of the user keys?
And then once I get the list of user keys, then how do I use that to iterate over the 'users' node to get the list of new users (my step #2 above)?
And then how to put those new users into an array (my step #3 above), and then get the number of new users for the 'badge' parameter when I send my push notification (my step #4 above)?
The problem is that this seems really inefficient. There has to be a better way to simply get a list of new users. There has to be some sort of query I can perform that will go over my 'users' node, see which ones have 'true' for their 'newUser' node, and get a count of those--instead of my roundabout way of getting a list of user from 'admin' node, then using that list to get a list of 'new users' from the 'users' node, then creating an array and then counting that array, then using that number to send to the 'badge' parameter on my push notification.
Any thoughts? I've been at this for days.
If it helps, I know Swift and the app is iOS. Thanks!!
UPDATE #2
So I opted to try and just get a snapshot of all users and bypass the 'admin' node altogether. Here is the code:
const db = admin.database();
const ref = db.ref('users');
return ref.once('value').then((adminSnap) => {
console.log('admin key:', adminSnap.key)
// create blank array to store
let newUserCount = 0;
// iterate over adminSnap to get each individual snap
adminSnap.forEach(function (userSnap) {
const userData = userSnap.val();
const userKey = userSnap.key
// console.log('email?', userData.email, 'user key:', userKey, 'new user?', userData.newUser)
if (userData.newUser === true) {
newUserCount++
console.log('new user:', userKey, userData.newUser, userData.email)
}
});
console.log(newUserCount)
})
This new code works and gives me the number for my badge parameter for when I perform my push notification, but I'm wondering if it's the most efficient way to do things. Plus, as my database grows in size, won't it tax the server / slow way down? And won't it cost me a lot of bandwidth for my Firebase account?
I thought this would be a simple thing to do, but it's turning into a bit of a hassle. I'm open to a different way to complete this. Thanks!
After even more research, I ended up abandoning my original approach. I decided to just create a new node on my Firebase database with the new user count and then update it via code from elsewhere. It's the simplest approach and will use the least amount of bandwidth.
Here is my final code:
function sendAlertToiPhone() {
console.log('test E')
// Get a database reference
const db = admin.database();
const ref = db.ref('stats');
ref.child('newUserCount').once('value').then((snapshot) => {
const newUserCount = snapshot.val()
console.log('new user count:', newUserCount)
// send to Phontaine's iPhone 6
const FCMToken = "blahbehtyblahblah"
const payload = {
notification: {
title: 'New User',
body: 'Moneypants has a new download.',
sound: 'default',
badge: String(newUserCount)
}
};
return admin.messaging().sendToDevice(FCMToken, payload)
.then(function (response) {
console.log("Successfully sent message:", response);
})
.catch(function (error) {
console.log("Error sending message:", error);
});
}).catch(function (err) {
console.log('new user count error:', err);
})
}

Categories

Resources