So we have 2 tables:
listings
users
Currently, i'm trying to retrieve all the information of the given users id where the fk_poster_id of the listings table is the foreign key with reference made to the users id by using the GET method.But when i try to execute the codes, i receive [] as the output. Is there a way to solve this?
Here's my current sql codes
DROP DATABASE snapsell;
CREATE DATABASE IF NOT EXISTS `snapsell`;
USE `snapsell`;
DROP TABLE IF EXISTS `users`;
DROP TABLE IF EXISTS `listings`;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(50) NOT NULL,
UNIQUE (username),
profile_pic_url VARCHAR(1000) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=INNODB;
-- THESE ARE JUST EXAMPLES AND TEST KITS.TO BE REMOVED BEFORE PRESENTATION.
INSERT INTO users (username, profile_pic_url) VALUES
("steve_jobs","https://upload.wikimedia.org/wikipedia/commons/thumb/f/f5/Steve_Jobs_Headshot_2010-CROP2.jpg/800px-Steve_Jobs_Headshot_2010-CROP2.jpg"),
("barack_obama","https://upload.wikimedia.org/wikipedia/commons/e/e9/Official_portrait_of_Barack_Obama.jpg"),
("kim_jung_un","https://upload.wikimedia.org/wikipedia/commons/d/d0/Kim_Jung-Un_-_Inter_Korean_Summit%28cropped%29_v1.jpg"),
("lee_kuan_yew","https://upload.wikimedia.org/wikipedia/commons/0/0f/Lee_Kuan_Yew.jpg");
CREATE TABLE listings (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(100) NOT NULL,
description_i VARCHAR(1000) NOT NULL,
price INT(6) NOT NULL,
fk_poster_id INT NOT NULL,
KEY fkPosterID (fk_poster_id),
CONSTRAINT FOREIGN KEY (fk_poster_id) REFERENCES users(id) ON DELETE NO ACTION ON UPDATE NO ACTION,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=INNODB;
-- THESE ARE JUST EXAMPLES AND TEST KITS.TO BE REMOVED BEFORE PRESENTATION.
INSERT INTO listings (title, description_i, fk_poster_id, price) VALUES
("iPhone 6s USED","In good condition. Camera and screen not working.","2","250"),
("Samsung S7 NOT USED","In bad condition. Screen fully smashed. Can't even operate.","3","10000");
CREATE TABLE offers (
id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
fk_offeror_id INT NOT NULL,
KEY fkOfferID (fk_offeror_id),
CONSTRAINT FOREIGN KEY (fk_offeror_id) REFERENCES users(id) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=INNODB;
SELECT * FROM users;
SELECT * FROM listings;
My current controller codes
var express = require('express');
var app = express();
const userJs = require('../model/user')
const listingJs = require('../model/listing')
var bodyParser = require('body-parser');
var urlencodedParser = bodyParser.urlencoded({ extended: false });
app.use(bodyParser.json()); //parse appilcation/json data
app.use(urlencodedParser);
app.get("/users/:user_id/listings/",(req,res) => {
var user_id = req.params.id;
userJs.getListingsByUserID(user_id, (error,results) => {
if (error) {
res.status(500).send("Internal Server Error")
}
res.status(200).send(results);
});
})
And my current user.js codes
var db = require('./databaseConfig.js')
const users = {getListingsByUserID: function (user_id, callback) {
const getListingsByUserIDQuery = 'SELECT u.id,l.title,l.description_i,l.price,l.fk_poster_id,l.created_at FROM listings l INNER JOIN users u ON u.id = l.fk_poster_id WHERE u.id = ?;';
db.query(getListingsByUserIDQuery,[user_id],(error,results) => {
if (error) {
callback(error,null);
return;
};
callback(null,results);
})
}
module.exports = users;
Just try to use Promise instead of callback like this:
const users =
{
function getListingsByUserID(user_id)
{
return new Promise((resolve, reject) =>
{
db.query(getListingsByUserIDQuery,[user_id],(error,results) =>
{
if (error)
{
return reject(error);
}
else
{
return resolve(results);
}
});
});
});
};
If you want result through callback method then try callback(null,results[0]);
Related
I'm having a hard time figuring out what's wrong with my code base or on my database since i was just trying to insert a device information to a table in reference to the user who owns it. no errors are being thrown but the device registration isn't working.
Here's the database
CREATE TABLE `users` (
`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
`email` varchar(255),
`password` varchar(255),
`firstname` varchar(255),
`lastname` varchar(255),
`dob` varchar(255),
`country` varchar(255),
`farmname` varchar(255),
`acctype` varchar(255),
`firmware` double
);
CREATE TABLE `controlModules` (
`id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
`deviceowner` int,
`devicename` varchar(255),
`serial#` varchar(255),
`devicestate` varchar(255),
`ipaddress` varchar(255),
`wanaddress` varchar(255),
`firmware` varchar(255)
);
ALTER TABLE `controlModules` ADD FOREIGN KEY (`deviceowner`) REFERENCES `users` (`id`);
Here's the function for react.js where it passes input data to backend
const email = sessionStorage.getItem("email");
const [name, setDeviceName] = useState("");
const [serial, setDeviceSerial] = useState("");
const [lanip, setDeviceLANIP] = useState("");
const [wanip, setDeviceWANIP] = useState("");
const [deviceStatus, setDeviceStatus] = useState("");
Axios.defaults.withCredentials = true;
const registerDevice =()=>{
Axios.post("http://localhost:3020/registerDevice", {
email: email,
name: name,
serial: serial,
lanip: lanip,
wanip: wanip,
}).then((response) => {
if (response) {
setDeviceStatus(response);
} else {
setDeviceStatus("error");
}
});
};
Here's the code for backend on node.js
app.post("/registerDevice", (req, res)=> {
const email = req.body.email;
const name = req.body.name;
const serial = req.body.serial;
const lanip = req.body.lanip;
const wanip = req.body.wanip;
const status = "online"
const firmware = "1.3";
console.log(email);
let stmt = `SELECT * FROM users WHERE id=?`;
let todo = [email];
//getting parentid
db.query(stmt, todo, (err, results, fields) => {
if (err) {
return console.error(err.message);
}
console.log(results)
const userid = results.id;
let statement = `INSERT INTO controlModules(deviceowner, devicename, serial#, devicestate, ipaddress, wanaddress, firmware) VALUES (?,?,?,?,?,?)`;
let task = [userid, name, serial, status, lanip, wanip, firmware];
//inserting to childtable
db.query(statement, task, (err, results, fields) => {
if (err) {
return console.error(err.message);
}
console.log(results);
});
});
Thanks for the help and enlightenment.
I'm a nodeJS beginner and am trying to learn it by creating a blog. To do so, I have three tables
CREATE TABLE `articles` (
`article_id` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(255) NOT NULL,
`content` longtext NOT NULL,
`image` varchar(255) NOT NULL,
`created` datetime NOT NULL,
`author_id` int(11) NOT NULL,
PRIMARY KEY (`article_id`)
)
CREATE TABLE `authors` (
`author_id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(255) NOT NULL,
PRIMARY KEY (`author_id`)
)
CREATE TABLE `comments` (
`comment_id` int(11) NOT NULL AUTO_INCREMENT,
`comment_content` longtext NOT NULL,
`created` datetime NOT NULL,
`comment_author` varchar(255) NOT NULL,
`id_article` int(11) NOT NULL,
PRIMARY KEY (`comment_id`)
)
On my page, I want to get all my articles, with their associated authors and comments.
This is my node code to get the data :
app.get('/api/articles', function(req, res){
connection.query('SELECT * FROM articles LEFT JOIN authors ON articles.author_id = authors.author_id LEFT JOIN comments ON articles.article_id = comments.id_article', function(err, row, fields){
if(!err){
res.json(rows);
}else
console.log('Error');
});
});
This query returns the data I need, but I want to parse it to get something that I can use easier in the front part, like
[
{
article_id: 1,
content: 'test',
title: 'test',
image: '',
author: {
author_id: 1,
email: 'test#test.com'
},
comments: [
{
comment_id: 1,
comment_content: 'test',
comment_author: 'test'
},
{
comment_id: 2,
comment_content: 'test',
comment_author: 'test'
}
]
}
]
Instead of the current return that looks like
[
{
article_id: 1,
title: 'test',
content: 'test',
image: '',
author_id: 1,
email: 'test#test.com',
comment_id: 1,
comment_content: 'test',
comment_author: 'test
}
]
I spent some time looking for something to do it, but couldn't find anything, so if someone knows how to do it, I'd be very grateful.
Thanks
You'll need to do two things:
(1) make sure you are sorting by article_id in your query
(2) create a tiny state machine, keeping track of the article_id, and loop through each record aggregating the comments. if your article_id changes, write the record to the table and move on to the next article:
var table = [];
var lastid = -1;
var article = {};
for(var i=0;i<rows.length;i++) {
var row = rows[i];
if (row.article_id!==lastid) {
//The id has changed, so create a new article
if (article.article_id) {
//If this isnt the first time looping, add the last article to the table
table.push(article);
}
article = {};
//create the structure you want
article.article_id = row.article_id;
article.title = row.title,
article.content = row.content,
article.image = row.image,
article.author = {
author_id: row.author_id,
email: row.email,
};
//comments go in this array. add the first one
article.comments = [{
comment_id:row.comment_id,
comment_content:row.commment_content,
comment_author:row.comment_author
}];
} else {
//same article, new comment
article.comments.push({
comment_id:row.comment_id,
comment_content:row.commment_content,
comment_author:row.comment_author
})
}
//update the id to check against the next row
lastid = row.article_id;
}
//make sure you push on the last article
table.push(article);
//Now you can send back the table in the new structure...
return table;
My tables (Mysql DB):
// Stores Table
CREATE TABLE IF NOT EXISTS `app_beta`.`stores` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
PRIMARY KEY (`id`))
// Items Table
CREATE TABLE IF NOT EXISTS `app_beta`.`items` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`user_id` INT UNSIGNED NOT NULL,
`title` TEXT NOT NULL,
`content` LONGTEXT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_items_user_id`
FOREIGN KEY (`user_id`)
REFERENCES `app_beta`.`users` (`id`))
// Products Table
CREATE TABLE IF NOT EXISTS `app_beta`.`products` (
`id` INT UNSIGNED NOT NULL,
`reviews` DECIMAL(7,1) NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_products_id`
FOREIGN KEY (`id`)
REFERENCES `app_beta`.`items` (`id`))
// Product_Store Table
CREATE TABLE IF NOT EXISTS `app_beta`.`products_stores` (
`product_id` INT UNSIGNED NOT NULL,
`store_id` INT UNSIGNED NOT NULL,
`price` DECIMAL(7,2) NOT NULL,
`url` VARCHAR(255) NOT NULL,
CONSTRAINT `fk_products_store_product_id`
FOREIGN KEY (`product_id`)
REFERENCES `app_beta`.`products` (`id`),
CONSTRAINT `fk_products_stores_store_id`
FOREIGN KEY (`store_id`)
REFERENCES `app_beta`.`stores` (`id`))
// Offers Table
CREATE TABLE IF NOT EXISTS `app_beta`.`offers` (
`id` INT UNSIGNED NOT NULL,
`store_id` INT UNSIGNED NOT NULL,
`price` DECIMAL(7,2) NULL,
`url` VARCHAR(255) NOT NULL,
`start_date` DATE NOT NULL,
`end_date` DATE NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_offers_store_id`
FOREIGN KEY (`store_id`)
REFERENCES `app_beta`.`stores` (`id`),
CONSTRAINT `fk_offers_id`
FOREIGN KEY (`id`)
REFERENCES `app_beta`.`items` (`id`))
Add. Info:
My tables are migrated. Just to clarify... the products and offers inherit from the items table. If the item is not created I can not add products and offers.
The product can have the title, summary, content, category etc... same for the offer.
The product can be on 1-many stores
The offer can be only on 1-1 store.
If I'm wrong LET ME KNOW!
** Please, I want someone to help me creating the relationships between the Item model, product and offer. Can i use polymorphic relations? **
Models DONE:
class Store extends Model
{
public function offers()
{
return $this->hasMany('App\Offer');
}
public function products()
{
return $this->hasMany('App\Product');
}
}
class Product extends Model
{
public function stores()
{
return $this->belongsToMany('App\Store');
}
}
class Offer extends Model
{
public function store()
{
return $this->belongsTo('App\Offer');
}
}
using php artisan tinker, all works nice!
namespace App
$user = new User
$store = new Store
$item = new Item
$item->id = 1
$item->user_id = 1
$item->title = 'test'
$item->content 'test'
$item->save();
true
$item2 = new Item
$item2->id = 2
....
true
$product1 = new Product
$product1->id = 1 (FK item->id)
$product1->reviews = 5
$product1->save()
true
$offer1 = new Offer
$offer1->id = 2 (FK item->id)
$offer1->store_id = 1
...
true
I'll add later a function to attach product to one or many stores (products_stores table).
Thanks.
This is how I think you can have a good start...
First of all, your model and migration can handle all it.
There is for relationship:Laravel 5.2 Relationship
There is for migration:Laravel 5.2 Migration
So there you create your migration:
Schema::create('stores', function (Blueprint $table) {
$table->bigIncrements('id')->unsigned();
$table->string('name', 50);
$table->timestamps();
});
Schema::create('items', function (Blueprint $table) {
$table->bigIncrements('id')->unsigned();
$table->bigInteger('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
$table->text('title');
$table->longText('content');
$table->timestamps();
});
Schema::create('products', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('store_id')->unsigned();
$table->foreign('store_id')->references('id')->on('stores');
$table->decimal('reviews', 7,1);
$table->timestamps();
});
Schema::create('offers', function (Blueprint $table) {
$table->bigIncrements('id');
$table->bigInteger('store_id')->unsigned();
$table->foreign('store_id')->references('id')->on('stores');
$table->bigInteger('item_id')->unsigned();
$table->foreign('item_id')->references('id')->on('items');
$table->decimal('price', 7,2);
$table->string('url', 255);
$table->dte('start_date');
$table->dte('end_date');
$table->timestamps();
});
So, once you did this, you can make your relationship onto your model. This way you don't need all the "between" tables. When you will use associate(), Laravel will create the link for you. This way you can do something like this: $offer->store()->name to get the name of the store of the current offer. Take a look:
Into Store's model
public function products()
{
return $this->hasMany(Product::class);
}
public function offers()
{
return $this->hasMany(Offer::class);
}
Into Offer's model
public function store()
{
return $this->belongsTo(Store::class);
}
This way, You create a one-to-many relation. Has I said, $offer->store() will retrieve the store of the offer. $store->offers()->get() will retrieve all offer of the store.
Hope it help.
EDIT
There is one only problem with what I said. The n + 1 problem. So like it explain there(search google "laravel n+1 problem" and pick the link to laracast) (can't put it as a link, not enough reputation) , when you call things like I said, the script will do 2 query. When you use a foreach() loop, it'll have as much loop +1 query. I suggest you to do things like that
$offers = Offer::with('store')->all();
This way you'ill have only 1 query and you will still able to do
$offer->store;
without doing another query.
When you use $model = Model::with('something')->all();, the query will fetch data from 2 table and return the result with an array into an array. Like this:
offers {
[0]:{a,b,c,d,e, store{a,b,c,d,e}}
[1]:{a,b,c,d,e, store{a,b,c,d,e}}
[2]:{a,b,c,d,e, store{a,b,c,d,e}}
[3]:{a,b,c,d,e, store{a,b,c,d,e}}
}
You can use the opposite:
$stores = Store::with('offers')->all();
So you can use:
$store->offers[i]->somthing;
Because the array will look like this:
stores {
[0]:{a,b,c,d,e, offers{
[0]:{a,b,c,d,e}
[1]:{a,b,c,d,e}
[2]:{a,b,c,d,e}
[3]:{a,b,c,d,e}
}}
[1]:{a,b,c,d,e, offers{
[0]:{a,b,c,d,e}
[1]:{a,b,c,d,e}
[2]:{a,b,c,d,e}
[3]:{a,b,c,d,e}
}}
[2]:{a,b,c,d,e, offers{
[0]:{a,b,c,d,e}
[1]:{a,b,c,d,e}
[2]:{a,b,c,d,e}
[3]:{a,b,c,d,e}
}}
}
I have the following model in NodeJS with sequelize and a MySQL database:
var Sequelize = require('sequelize');
var User = sequelize.define('user', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
...
};
I am trying to add a new user to my databse with the below code:
sequelize.transaction().then(function(t) {
User.create({/* User data without id */}, {
transaction: t
}).then(function() {
t.commit();
}).catch(function(error) {
t.rollback();
});
});
After that, I am getting the next error:
Executing (47f19f7b-a02d-4d72-ba7e-d5045520fffb): START TRANSACTION;
Executing (47f19f7b-a02d-4d72-ba7e-d5045520fffb): SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Executing (47f19f7b-a02d-4d72-ba7e-d5045520fffb): SET autocommit = 1;
Executing (47f19f7b-a02d-4d72-ba7e-d5045520fffb): INSERT INTO `user` (`id`, /* next fields */) VALUES (DEFAULT, /* next values */);
Executing (47f19f7b-a02d-4d72-ba7e-d5045520fffb): ROLLBACK;
And the error message:
[SequelizeDatabaseError: ER_NO_DEFAULT_FOR_FIELD: Field 'id' doesn't have a default value]
name: 'SequelizeDatabaseError',
message: 'ER_NO_DEFAULT_FOR_FIELD: Field \'id\' doesn\'t have a default value'
However, if I manually set the id value, it works. It seems sequelize is trying to set a default value in the id field, instead setting an autoincrement integer. I have defined this field as autoIncrement in my database too.
How could I do this insertion? Do I have to set the id manually?
EDIT
This is my table definition:
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`uid` varchar(9) NOT NULL,
`name` varchar(20) NOT NULL,
`email` varchar(30) DEFAULT NULL,
`birthdate` date NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uid_UNIQUE` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
You must be sure you're not even sending the id key at all.
I have done a quick minimal test and it seemed to work great:
var Sequelize = require('sequelize');
var sequelize = new Sequelize('cake3', 'root', 'root', {
define: {
timestamps: false
},
});
var User = sequelize.define('user1', {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true
},
name: {
type: Sequelize.STRING
}
});
sequelize.transaction().then(function(t) {
User.create({name:'test'}, {
transaction: t
}).then(function() {
t.commit();
}).catch(function(error) {
console.log(error);
t.rollback();
});
});
Table dump:
CREATE TABLE `user1s` (
`id` int(11) NOT NULL,
`name` varchar(20) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
ALTER TABLE `user1s`
ADD PRIMARY KEY (`id`);
ALTER TABLE `user1s`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT,AUTO_INCREMENT=1;
In migration, add this line of code:
await queryInterface.sequelize.query("ALTER TABLE table_name AUTO_INCREMENT = 1000000;");
Suppose I have the following server.js file:
server.js
var express = require('express');
var app = express();
var mysql = require('mysql');
var dbhelpers = require('./public/database_helpers.js')
var bodyParser = require('body-parser')
app.use(express.static(__dirname + '/public'));
app.use(express.static(__dirname + '/public/views'));
app.use(express.static(__dirname + '/public/controlers'));
app.use(express.static(__dirname + '/public/lib'));
app.use(bodyParser())
var connection = mysql.createConnection({
**Correct info**
});
connection.connect(function(err){
if(!err) {
console.log("Database is connected ... \n\n");
} else {
console.log("Error connecting database ... \n\n");
}
});
app.post('/signup',function(req,res){
var newUser = req.body;
connection.query('INSERT INTO users SET ?',newUser, function(err, rows,fields){
if (!err){
console.log("posted to database")
res.sendStatus(200);
} else{
console.log('Error while performing Query.');
res.sendStatus(500);
}
});
})
app.get('/artistsearch',dbhelpers.checkDbArtist)
app.post('/artistsearch', dbhelpers.insertDb)
app.post('/reviews',dbhelpers.insertReviewDb)
app.listen(process.env.PORT || 3000);
console.log("Listening at 3000")
I have recently deployed to heroku and used the clearDB addon since I am using MySQL. The logs indicate that I have been able to connect to the database, but the thing is that I believe Heroku creates an empty database. How can I create the following schema in my with clearDB:
schema.sql
CREATE TABLE users(
users_id INT NOT NULL AUTO_INCREMENT,
user_username VARCHAR(100) NOT NULL,
user_password VARCHAR(40) NOT NULL,
PRIMARY KEY ( users_id )
);
CREATE TABLE artist(
artist_id INT NOT NULL AUTO_INCREMENT,
artist_name VARCHAR(100) NOT NULL,
artist_genre VARCHAR(100) NOT NULL,
artist_imageurl VARCHAR(100) NOT NULL,
artist_bio VARCHAR(1000) NOT NULL,
PRIMARY KEY ( artist_id )
);
CREATE TABLE reviews (
review_id INT NOT NULL AUTO_INCREMENT,
user_name VARCHAR(100) NOT NULL,
venue VARCHAR(100) NOT NULL,
number_of_stars INT NOT NULL,
review_details VARCHAR(10000) NOT NULL,
artist_id VARCHAR(100) NOT NULL,
PRIMARY KEY ( review_id )
);
Anyone had any idea?
First, you should type heroku config to get your clearDB credentials.
Then, you can ran this command from your terminal : mysql --host=us-cdbr-east.cleardb.com --user=xxxx --password=xxxx --reconnect heroku_xxxxxx < schema.sql