In Sequelize.js I have query to find all items under some condition. After I got array of model instances I want to delete those instances:
let toBeDeleted = await Request.findAll({
where: {
// Some where statements...
}
});
const deleted = await toBeDeleted.destroyAll(); // <= Need something like this
// Some actions with array `toBeDeleted` (For example, Delete file associated with each row)
for (let i in toBeDeleted)
await fs.removeSync(path.join(global.config.paths.screenshots, toBeDeleted[i].image));
I need to delete what I found first and then delete associated files with row.
Update
use where once and then destroy using findAll data. replace below code with delete part of the original answer.
await Request.transaction(async function (t) {
for ( var i = 0; i < toBeDeleted.length; i++){
await toBeDeleted[i].destroy({ transaction: t });
}
});
like this ?
let toBeDeleted = await Request.findAll({
where: {
// Some where statements...
}
});
const deleted = await Request.destroy({
where: {
// the same statements you used to find toBeDeleted
}
});
keep in mind if you have paranoid: true , then records will not be deleted and only deletedAt column will have a time string, if you want to force delete the record you need to use force:true
const { Op } = require("sequelize");
let toBeDeleted = await Request.findAll({
where: {
// Some where statements...
}
});
// get ids of scoped instances that you want to delete
const toBeDeletedIds = toBeDeleted.map(el => el.id);
await Request.destroy({
where: {
[Op.and]: {
id: toBeDeletedIds, // this will make your destroy scoped to this ids
// Some where statements...
}
}
}
})
Related
Hello I'm trying to take data from a sql table but the data that I want to check is into an array, so I need compare the data to check if an user is into the group, the array only have the IDs from users and the specific ID that I want is being bringing to me through the login.
This code is in Typescript.
If you need more information let me know please.
class CompanyController {
async consultCompanys(req: Request, res: Response) {
let response: ResponseModel = new ResponseModel(ECodeResponse.Ok, "", []);
const { UserId } = req.body;
try {
const Companies: any = await pool.query(
`SELECT (CompanyId) From Companies Where Members = '${UserId}'`
);
response.Code = ECodeResponse.Ok;
response.Message = EWarningMessage.Error;
return res.json(response);
} catch (error) {
response.Code = ECodeResponse.Warning;
response.Message = EWarningMessage.Error;
return res.json(response);
}
}
}
I'm a litle oxidated in this kind of consults
I use react native through firebase database
I have a database creating products each product has a number
I want to take a number and compare it with the product number
And if there is then I want to get a product
the function its give me my correct name but where i use it on render its not found the variable (name)
getAllContact = async key => {
let barCodeData2 = this.props.navigation.state.params.barcodeData
let self = this;
let contactRef = firebase.database().ref()
contactRef.on("value", dataSnapsot => {
if (dataSnapsot.val()) {
let contactResult = Object.values(dataSnapsot.val())
let contactKey = Object.keys(dataSnapsot.val())
contactKey.forEach((value, key) => {
contactResult[key]["key"] = value
})
self.setState({
fname: contactResult.fname,
data: contactResult.sort((a, b) => {
var nameA = a.barcode
var nameB = barCodeData2
const name = a.fname
console.log(`${nameA} What numers issssssss`);
if (nameA == nameB) {
alert(`${name} ........`)
console.log(`${nameA == nameB}is Equqlqlqlql`);
return name
}
}),
})
}
})
}
render() {
let t=this.state.name
alert(`${t} how?`)// is give Not found
// let d = this.props.navigation.state.params.barcodeData
return (
)
}
When you try such a comparison query i.e.
let ref = firebase.firestore();
ref.collection('zoo')
.where("id", "==", myID)
.get()
.then((snapshot) => {
console.log(snap.empty); //this will denote if results are empty
snapshot.forEach(snap => {
console.log(snap.exists); //alternatively this will also tell you if it is empty
})
})
well what you can do is run query based on you product no and if there's a product you will a product if there's none you will get an empty array.
read firebase documentation on queries
https://firebase.google.com/docs/reference/js/firebase.database.Query
I'm trying to get information (true/false) from AsyncStorage in a function and create a string which is importent to fetch data in the next step. My problem is, the function is not finished until the string is required.
I tried many solutions from the internet like async function and await getItem or .done() or .then(), but none worked out for me.
//_getFetchData()
AsyncStorage.getAllKeys().then((result) => { //get all stored Keys
valuelength = result.length;
if (valuelength !== 0) {
for (let i = 0; i < valuelength; i++) {
if (result[i].includes("not") == false) { //get Keys without not
AsyncStorage.getItem(result[i]).then((resultvalue) => {
if (resultvalue === 'true') {
if (this.state.firstValue) {
this.state.channels = this.state.channels + "channel_id" + result[i];
console.log("channel: " + this.state.channels);
}
else {
this.state.channels = this.state.channels + "channel" + result[i];
}
}
});
}
return this.state.channels;
_fetchData() {
var channel = this._getFetchData();
console.log("channel required: " + channel);
}
The current behaviour is that the console displays first "channel required: " than "channel: channel_id0".
Aspects in your question are unclear:
You don't say when this.state.firstValue is set, and how that relates to what you are trying to accomplish.
You have a for-loop where you could be setting the same value multiple times.
You mutate the state rather than set it. This is not good, see this SO question for more on that.
There are somethings we can do to make your code easier to understand. Below I will show a possible refactor. Explaining what I am doing at each step. I am using async/await because it can lead to much tidier and easier to read code, rather than using promises where you can get lost in callbacks.
Get all the keys from AsyncStorage
Make sure that there is a value for all the keys.
Filter the keys so that we only include the ones that do not contain the string 'not'.
Use a Promise.all, this part is important as it basically gets all the values for each of the keys that we just found and puts them into an array called items
Each object in the items array has a key and a value property.
We then filter the items so that only the ones with a item.value === 'true' remain.
We then filter the items so that only the ones with a item.value !== 'true' remain. (this may be optional it is really dependent on what you want to do)
What do we return? You need to add that part.
Here is the refactor:
_getFetchData = async () => {
let allKeys = await AsyncStorage.getAllKeys(); // 1
if (allKeys.length) { // 2
let filteredKeys = allKeys.filter(key => !key.includes('not')); // 3
let items = await Promise.all(filteredKeys.map(async key => { // 4
let value = await AsyncStorage.getItem(key);
return { key, value }; // 5
}))
let filteredTrueItems = items.filter(item => items.value === 'true'); // 6
let filteredFalseItems = items.filter(item => items.value !== 'true'); // 7
// now you have two arrays one with the items that have the true values
// and one with the items that have the false values
// at this points you can decide what to return as it is not
// that clear from your question
// return the value that your want // 8
} else {
// return your default value if there are no keys // 8
}
}
You would call this function as follows:
_fetchData = async () => {
let channel = await this._getFetchData();
console.log("channel required: " + channel);
}
Although the above will work, it will not currently return a value as you haven't made it clear which value you wish to return. I would suggest you build upon the code that I have written here and update it so that it returns the values that you want.
Further reading
For further reading I would suggest these awesome articles by Michael Chan that discuss state
https://medium.learnreact.com/setstate-is-asynchronous-52ead919a3f0
https://medium.learnreact.com/setstate-takes-a-callback-1f71ad5d2296
https://medium.learnreact.com/setstate-takes-a-function-56eb940f84b6
I would also suggest taking some time to read up about async/await and promises
https://medium.com/#bluepnume/learn-about-promises-before-you-start-using-async-await-eb148164a9c8
And finally this article and SO question on Promise.all are quite good
https://www.taniarascia.com/promise-all-with-async-await/
Using async/await with a forEach loop
Try this instead. Async functions and Promises can be tricky to get right and can be difficult to debug but you're on the right track.
async _getFetchData() {
let channels = "";
let results = await AsyncStorage.getAllKeys();
results.forEach((result) => {
if (result.includes("not") === false) {
let item = await AsyncStorage.getItem(result);
if (item === 'true') {
console.log(`channel: ${result}`)
channels = `channel_id ${result}`;
}
}
});
return channels;
}
_fetchData() {
this._getFetchData().then((channels) => {
console.log(`channel required: ${channel}`);
});
}
what if you wrap the _getFetchData() in a Promise? This would enable you to use
var channel = this._getFetchData().then(console.log("channel required: " + channel));
Otherwise the console.log won't wait for the execution of the _getFetchData().
This is what the console.log is telling you. it just logs the string. the variable is added after the async operation is done.
UPDATE
I would try this:
//_getFetchData()
AsyncStorage.getAllKeys().then((result) => { //get all stored Keys
valuelength = result.length;
if (valuelength !== 0) {
for (let i = 0; i < valuelength; i++) {
if (result[i].includes("not") == false) { //get Keys without not
AsyncStorage.getItem(result[i]).then((resultvalue) => {
if (resultvalue === 'true') {
if (this.state.firstValue) {
this.state.channels = this.state.channels + "channel_id" + result[i];
console.log("channel: " + this.state.channels);
}
else {
this.state.channels = this.state.channels + "channel" + result[i];
}
}
});
}
return new Promise((resolve, reject) => {
this.state.channels !=== undefined ? resolve(this.state.channels) : reject(Error('error '));
}
_fetchData() {
var channel = this._getFetchData().then(console.log("channel required: " + channel));
}
maybe you must change the this.state.channels !=== undefined to an expression that's matches the default value of this.state.channels.
I got something strange with pg-promise with a transaction with generators.
This is what I want :
Get or register a user (getOrRegisterUser)
Do batch stuff (4 inserts generator)
Finally , do the last insert (generator registerCall) with the result of getOrRegisterCurrentParkingIfProvided generator
Here is my code :
db.tx(function (t) {
return t.task.call(params, getOrRegisterUser).then(function (user) {
params.masterId = user.id; // NOTICE : MY USER ID DATABASE
return t.batch([
t.task.call(params, registerNewPhones),
t.task.call(params, registerNewPlate),
t.task.call(params, registerNewSubscriptions),
t.task.call(params, getOrRegisterCurrentParkingIfProvided)
]).then(function (result) {
params.ParkingId = (result[3] !== undefined) ? result[3].id : null;
return t.task.call(params, registerCall);
})
});
}).then(function () {
// job done
resolve();
}).catch(function (err) {
console.log(err);
reject(err);
});
I got this error message at the second generator (registerNewPhones) :
severity: 'ERREUR',
code: '23503',
detail: 'La clé (customer)=(3) n\'est pas présente dans la table « users ».',
Any way to solve this ? I tried transactions like this : https://github.com/vitaly-t/pg-promise#nested-transactions or https://github.com/vitaly-t/pg-promise#synchronous-transactions but with some unknown circumstances I still got error somewhere.
Thanks
PS: I know that the implementation of these generators aren't guilty so ...
EDIT: if you really want to see the code
let squel = require('squel');
// squel with PostgresSQL syntax
let squelPostgres = squel.useFlavour('postgres');
registerNewPhones :
// Register all new phones numbers for user
function * registerNewPhones(t) {
let params = t.ctx.context;
let findPhonesForUserQuery = squelPostgres
.select()
.from("HELPDESK.phones")
.field("number")
.where("customer = ?", params.masterId)
.toString();
let registerPhoneForUser = squelPostgres
.insert()
.into("HELPDESK.phones")
.set("customer", params.masterId);
// find the already known phone number(s) for this user
return t.any(findPhonesForUserQuery).then(function (result) {
// data
let phones = (params.hasOwnProperty("phones") ? params.phones : []);
let alreadyRegisteredPhones = result.map(function (element) {
return element.number;
});
// filter data
let phonesToRegister = phones.filter(function (aPhoneNumber) {
return alreadyRegisteredPhones.indexOf(aPhoneNumber) == -1;
});
// create queries
let queries = phonesToRegister.map(function (phone) {
return db.none(
registerPhoneForUser
.clone()
.set("number", phone)
.toString()
);
});
return t.batch(queries);
});
}
and the generator getOrRegisterUser:
function * getOrRegisterUser(t) {
let params = t.ctx.context;
// QUERIES:
let findUserQuery = squelPostgres
.select()
.from("HELPDESK.users")
.field("id")
.where("registered_id = ?", params.userId)
.toString();
let insertUserQuery = squelPostgres
.insert()
.into("HELPDESK.users")
.setFields({
name: params.userName,
registered_id: params.userId,
typeOfAccount: 'BASIC',
email: params.email
})
.returning('id')
.toString();
let user = yield t.oneOrNone(findUserQuery);
return yield user || t.one(insertUserQuery);
}
The issue is within the ES6-Generator function registerNewPhones:
return t.any(findPhonesForUserQuery)...
it doesn't yield the promise result, which is required for ES6 Generator functions.
i.e. it must be:
return yield t.any(findPhonesForUserQuery)...
I'd like a npm script to create/configure/etc. and finally import a SQL dump. The entire creation, configuring, etc. is all working, however, I cannot get the import to work. The data never is inserted. Here's what I have (nevermind the nested callback as they'll be turned into promises):
connection.query(`DROP DATABASE IF EXISTS ${config.database};`, err => {
connection.query(`CREATE DATABASE IF NOT EXISTS ${config.database};`, err => {
connection.query('use DATABASENAME', err => {
const sqlDumpPath = path.join(__dirname, 'sql-dump/sql-dump.sql');
connection.query(`SOURCE ${sqlDumpPath}`, err => {
connection.end(err => resolve());
});
})
});
});
I also tried the following with Sequelize (ORM):
return new Promise(resolve => {
const sqlDumpPath = path.join(__dirname, 'sql-dump/sql-dump.sql');
fs.readFile('./sql/dump.sql', 'utf-8', (err, data) => {
sequelize
.query(data)
.then(resolve)
.catch(console.error);
});
});
Here's how I set up my initial Sequelized import using the migrations framework. There is plenty of going on here but in short I:
find the latest sql-dump in the migrations folder
read the file using fs
split the text into queries
check if its a valid query and if so apply some cleaning that my data required (see related post)
push an array full of queries - I start with making sure that the database is clean by calling the this.down first
run everything as a promise (as suggested here) using the mapSeries (not the map)
Using sequelize-cli you can in your shell create a migration by writing:
sequelize migration:create
And you will automatically have the file where you enter the code below. In order to execute the migration you simply write:
sequelize db:migrate
"use strict";
const promise = require("bluebird");
const fs = require("fs");
const path = require("path");
const assert = require("assert");
const db = require("../api/models"); // To be able to run raw queries
const debug = require("debug")("my_new_api");
// I needed this in order to get some encoding issues straight
const Aring = new RegExp(String.fromCharCode(65533) +
"\\" + String.fromCharCode(46) + "{1,3}", "g");
const Auml = new RegExp(String.fromCharCode(65533) +
String.fromCharCode(44) + "{1,3}", "g");
const Ouml = new RegExp(String.fromCharCode(65533) +
String.fromCharCode(45) + "{1,3}", "g");
module.exports = {
up: function (queryInterface, Sequelize) {
// The following section allows me to have multiple sql-files and only use the last dump
var last_sql;
for (let fn of fs.readdirSync(__dirname)){
if (fn.match(/\.sql$/)){
fn = path.join(__dirname, fn);
var stats = fs.statSync(fn);
if (typeof last_sql === "undefined" ||
last_sql.stats.mtime < stats.mtime){
last_sql = {
filename: fn,
stats: stats
};
}
}
}
assert(typeof last_sql !== "undefined", "Could not find any valid sql files in " + __dirname);
// Split file into queries
var queries = fs.readFileSync(last_sql.filename).toString().split(/;\n/);
var actions = [{
query: "Running the down section",
exec: this.down
}]; // Clean database by calling the down first
for (let i in queries){
// Skip empty queries and the character set information in the 40101 section
// as this would most likely require a multi-query set-up
if (queries[i].trim().length == 0 ||
queries[i].match(new RegExp("/\\*!40101 .+ \\*/"))){
continue;
}
// The manual fixing of encoding
let clean_query = queries[i]
.replace(Aring, "Å")
.replace(Ouml, "Ö")
.replace(Auml, "Ä");
actions.push({
query: clean_query.substring(0, 200), // We save a short section of the query only for debugging purposes
exec: () => db.sequelize.query(clean_query)
});
}
// The Series is important as the order isn't retained with just map
return promise.mapSeries(actions, function(item) {
debug(item.query);
return item.exec();
}, { concurrency: 1 });
},
down: function (queryInterface, Sequelize) {
var tables_2_drop = [
"items",
"users",
"usertypes"
];
var actions = [];
for (let tbl of tables_2_drop){
actions.push({
// The created should be created_at
exec: () => db.sequelize.query("DROP TABLE IF EXISTS `" + tbl +"`")
});
}
return promise.map(actions, function(item) {
return item.exec();
}, { concurrency: 1 });/**/
}
};
Based loosely on Max Gordon's answer, here's my code to run a MySQL Dump file from NodeJs/Sequelize:
"use strict";
const fs = require("fs");
const path = require("path");
/**
* Start off with a MySQL Dump file, import that, and then migrate to the latest version.
*
* #param dbName {string} the name of the database
* #param mysqlDumpFile {string} The full path to the file to import as a starting point
*/
module.exports.migrateFromFile = function(dbName, mysqlDumpFile) {
let sequelize = createSequelize(dbName);
console.log("Importing from " + mysqlDumpFile + "...");
let queries = fs.readFileSync(mysqlDumpFile, {encoding: "UTF-8"}).split(";\n");
console.log("Importing dump file...");
// Setup the DB to import data in bulk.
let promise = sequelize.query("set FOREIGN_KEY_CHECKS=0"
).then(() => {
return sequelize.query("set UNIQUE_CHECKS=0");
}).then(() => {
return sequelize.query("set SQL_MODE='NO_AUTO_VALUE_ON_ZERO'");
}).then(() => {
return sequelize.query("set SQL_NOTES=0");
});
console.time("Importing mysql dump");
for (let query of queries) {
query = query.trim();
if (query.length !== 0 && !query.match(/\/\*/)) {
promise = promise.then(() => {
console.log("Executing: " + query.substring(0, 100));
return sequelize.query(query, {raw: true});
})
}
}
return promise.then(() => {
console.timeEnd("Importing mysql dump");
console.log("Migrating the rest of the way...");
console.time("Migrating after importing mysql dump");
return exports.migrateUp(dbName); // Run the rest of your migrations
}).then(() => {
console.timeEnd("Migrating after importing mysql dump");
});
};