hasmany in express js not working with sequelize - express

I have created models Skills and Members
Member Table:
id username password created
1 gagandeep 99703dd91da5b0cabf496d49af0ab03c2dfe7788 2017-08-14 05:59:46
Skills Table:
id member_id skill
1 1 programming
2 1 music
Code:
Model
var Member=Seq.define('members',{}, {});
var Skills=Seq.define('skills',{}, {});
Member.hasMany(Skills,{as: 'skills', through: 'skills', foreignKey:'member_id'});
Call:
router.route('/test').get(function(req, resp){
Member.findAll({include: [{model: Skills}]},{
raw:true
}).success(onSuccess).error(onError);
function onSuccess(data){
resp.json(data);
}
function onError(data){
resp.json(data);
}
});
But Node js showing error as below:
Error: skills is not associated to members! at DAOFactory.validateIncludedElement (C:\Users\promatics\Desktop\netpar\node_modules\sequelize\lib\dao-factory.js:1476:13) at DAOFactory.validateIncludedElements (C:\Users\promatics\Desktop\netpar\node_modules\sequelize\lib\dao-factory.js:1388:59) at DAOFactory.module.exports.DAOFactory.findAll (C:\Users\promatics\Desktop\netpar\node_modules\sequelize\lib\dao-factory.js:458:34) at Object.handle (C:\Users\promatics\Desktop\netpar\demo.js:72:9) at next_layer (C:\Users\promatics\Desktop\netpar\node_modules\express\lib\router\route.js:103:13) at Route.dispatch (C:\Users\promatics\Desktop\netpar\node_modules\express\lib\router\route.js:107:5) at C:\Users\promatics\Desktop\netpar\node_modules\express\lib\router\index.js:195:24 at Function.proto.process_params (C:\Users\promatics\Desktop\netpar\node_modules\express\lib\router\index.js:251:12) at next (C:\Users\promatics\Desktop\netpar\node_modules\express\lib\router\index.js:189:19) at next (C:\Users\promatics\Desktop\netpar\node_modules\express\lib\router\index.js:166:38)

You don't actually need that through statement. You only use through when you have an association between two tables through a junction table. What I would do here is something like...
var Member = Seq.define('members', {
// Some attributes...
});
var Skills = Seq.define('skills', {
// Some attributes...
});
Member.hasMany(Skills, {
as: 'skills',
// Remove `through`!
foreignKey: 'member_id'
});
// Want to query for all members with the skills joined?
Member.findAll({
include: {
model: Skills,
as: 'skills'
}
});
That should get you the results you are looking for. Each member object will have reference to an inner skills key, which will be an array of skills associated to the user.
Good luck :)

Related

apply count on inner join in sql using sequelize

If i have Posts model and Likes model that PostsLikes model has postID as foreign key
How to create orm sequelize query to get post by id and number of likes on it
You should use a subquery in attributes options like this:
const posts = await Posts.findByPk(postId, {
attributes: {
include: [[Sequelize.literal('SELECT COUNT(*) FROM PostsLikes where PostsLikes.postID = Posts.ID)'), 'LikesCount']]
}
})

Supabase, filter by column value of foreign key row

I am trying to figure out how to implement a query in supabase:
Schema
CREATE TABLE cars
(
id SERIAL PRIMARY KEY,
brand TEXT
);
CREATE TABLE stores
(
id SERIAL PRIMARY KEY,
car INT REFERENCES car(id),
name TEXT
);
I want to get all stores which carry the car of brand "x"
In Supabase I can filter like this:
let { data: stores } = await supabase
.from('stores')
.select("*")
.eq('name', 'Ford car shop')
// Returns
{
id: 123456,
car:"Ford",
name:"Ford car shop"
}
or join like this:
let { data: stores } = await supabase
.from('stores')
.select(`
*,
cars (
brand
)
`)
.eq('name', 'Ford car shop')
// Returns
{
id: 123456,
car:"Ford",
cars: {
id: 654321,
brand: "Ford"
}
name:"Ford car shop"
}
But how can I filter stores by the brand of the car they carry using the supabase sdk?
2022: This is now possible with supabase client. You can use the !inner() function.
let { data: stores } = await supabase
.from('stores')
.select('*, cars!inner(*)')
.eq('cars.brand', 'Ford')
Doc here: Filtering with inner joins
You can use the built in postgrest api supabase gives you to get this info. e.g:
/projects?select=*,clients!inner(*)&clients.id=eq.12
this isn't added to the supabase client yet.
the patch is shown here: https://github.com/PostgREST/postgrest/releases/tag/v9.0.0
Edit:
Supabase recently added this feature. The new accepted answer is below.
I did some more research and found out that this is currently not possible. However, it seems like it has been implemented and will make it into the next Supabase release.
An interim solution is using views and then querying those.
CREATE VIEW stores_expanded AS
SELECT
stores.id,
stores.name,
cars.brand
FROM
stores
LEFT JOIN cars
ON
stores.car = cars.id;
let { data: stores } = await supabase
.from('stores')
.select("*")
.eq('brand', 'x')

Why is POST request with pool.query only works intermittently when using :id in the middle of URL?

I wasn't quite sure how to phrase this question so feel free to make corrections to improve it as desired.
My goal is to make an HTTP POST that will create comments for a post and add the comment to the database comments table. I believe this necessitates doing an INSERT as well as a JOIN to add the specific POST id to the comment.
This is my first time including two requests in one query so I am unsure if this is correct. I had read about using a UNION but haven't been able to figure out the correct syntax as none of the examples included quotes '' around their requests.
My post route:
router.post(`/posts/:id/comments`, (request, response, next) => {
const { id } = request.params; // tried with and without brackets {}
const { comment_body } = request.body;
// Testing for correct params
console.log(id);
console.log(comment_body);
pool.query(
'INSERT INTO comments(comment_body) VALUES($1)',
[post_id, comment_body],
'SELECT * FROM comments JOIN posts ON posts.post_id = commments.post_id',
(err, res) => {
if (err) return next(err);
}
);
});
What is strange is that this worked twice then stopped working. There are two entries in the comments table but any further posts don't do anything. This only worked from the comments form and not yet in Postman
This worked in two separate tests. When using brackets around the id, the post was created in the table but no post_id was joined on this table:
const { id } = request.params;
If I didn't use the brackets, the post_id was created in the data table:
const id = request.params;
Here are my tables:
CREATE TABLE posts(
post_id SERIAL,
user_id INT,
post_body CHARACTER varying(20000)
);
CREATE TABLE comments(
id SERIAL,
post_id INT,
user_id INT,
comment_body CHARACTER varying(20000)
);
Originally I had the post_id for comments set as serial but figured if that is supposed to be joined from the posts.post_id, it would probably need to be INT.
Thanks much for any direction.
I managed to solve this with the following:
router.post(`/posts/:id/comments`, async (request, response, next) => {
try {
const { id } = request.params;
const { comment_body } = request.body;
await pool.query
('INSERT INTO comments(post_id, comment_body) VALUES($1, $2)',
[id, comment_body]);
} catch(error) {
console.log(error.message)
}
});
Rather than using the JOIN, I just included the posts ID parameter in the original INSERT and imported it that way. I had initially thought I had to do it as a join but couldn't get a second SQL request to work. Thanks to snakecharmerb for the idea.
I also added async/await.

Laravel/SQL: How to fetch data from multiple table in a single query? that too using 'where'

Working on a search functionality on Laravel App(Blog/Posts).
There are multiple types of posts (each having a separate table in the database)
Like Business posts, Social Life posts etc..
Below is the search function on SearchController
class SearchController extends Controller
{
public function search(Request $request, $query = null)
{
if($query == null)
return redirect()->route('home');
$search = Business::where([['title','like','%'.$query.'%'],['status','=',1]])
->orWhere([['description','like','%'.$query.'%'],['status','=',1]])
->paginate(10);
return view('front.search',[
'results' => $search,
'query' => $query
]);
}
}
So basically my question is how to add other types of Post's table also?
My main motive is that when someone searches for anything, the result should be fetched from all types of posts table(business, nature, life & so on..).
You have to maintain common id in both the table
NOTE: Join is the preferable method
$querys = DB::table('Business')->where([['Business.title','like','%'.$query.'%'],['Business.status','=',1]])
->orWhere([['Business.description','like','%'.$query.'%'],['Business.status','=',1]]);
$querys->join('socialtable','socialtable.userid','=','Business.userid');
// Just join the social table
$querys->where('socialtable.title', 'like','%'.$query.'%');
$result = $querys->paginate(10);
If you have a model called Book, like this:
class Book extends Model
{
/**
* Get the author that wrote the book.
*/
public function author()
{
return $this->belongsTo('App\Author');
}
}
Then you can retrieve all of your books with authors like this:
$books = App\Book::with(['author'])->get();
Check out Eager loading from Laravel documentation.
Just add table name before every field
$querys = DB::table('Business')->where([['Business.title','like','%'.$query.'%'],['Business.status','=',1]])
->orWhere([['Business.description','like','%'.$query.'%'],['Business.status','=',1]]);
$querys->join('socialtable','socialtable.userid','=','Business.userid');
// Just join the social table
$querys->where('socialtable.title', 'like','%'.$query.'%');
$result = $querys->paginate(10);

GORM Domain Mapping Issue

I've got a bit of a complicated domain model I'm trying to implement and I'm having some trouble. (On top of that, I'm quite new to all this!)
I have a User domain which has multiple roles and multiple tests. The Role domain works great. The Test domain is a bit more compilciated though because it requires two foreign keys instead of just 1 like in the Role domain. The first foreign key is the user_id and the second is a uni_id (university ID).
The User domain model contains the following
class User {
static hasMany = [roles:Role, tests:Test]
Integer userId
...
static mapping = {
table 'user_data'
id generator: 'assigned', name: 'userId', type: 'long'
userId column: 'user_id'
version false
roles joinTable:[name:'user_role', key:'user_id']
tests joinTable:[name:'user_test', key:'user_id'] // Here is where I run into trouble
}
static constraints = {
}
}
The Test domain contains
class Test {
static belongsTo = User
static hasMany = [users:User]
static hasOne = [uni:Uni]
Integer testId // primary key
String testType
static mapping = {
table 'test'
id generator: 'assigned', name: 'testId', type: 'long'
testId column: 'test_id'
users joinTable:[name:'user_test', key:'test_id']
uni joinTable:[name:'user_test', key:'test_id'] // If I leave this out, everything is groovy
version false
}
static constraints = {
}
}
and the Uni domain contains
class Uni {
static belongsTo = Test
static hasMany = [tests:Test]
Integer uniId // primary key
String shortName
String fullName
static mapping = {
table 'uni'
id generator: 'assigned', name: 'uniId', type: 'long'
uniId column: 'uni_id'
version false
tests joinTable:[name:'user_test', key:'uni_id']
}
static constraints = {
}
}
If its not clear, what I'm trying to do is pull in the University ID, Test ID, and User ID to a table user_test to find based on the User ID which tests they have taken. Is there a simple way to do this?
The kinds of errors I'm getting lead me to believe that for some reason it is trying to perform all actions on the table test instead of user_test. For example,
Unsuccessful: alter table test add uni_id int not null
I'd like to be able to access the test and university information corresonding to the specific user via user.tests.testType and user.tests.uni.fullName or something to that extent. What am I doing wrong? More importantly, is there a better way to do this?! Thanks in advance!
Edit 1: something interesting I just thought of.. a user can have multiple tests, but the inverse isn’t true. A given test will never be shared among multiple people. So I think that changes things a bit.. I'll do some reading and post if I come up with anything new.
Edit 2: Here's the Role domain
class Role {
static belongsTo = User
static hasMany = [users:User]
Integer roleId
String shortName
String roleName
Integer roleLevel
static mapping = {
table 'role'
id generator: 'assigned', name: 'roleId', type: 'long'
roleId column: 'role_id'
users joinTable:[name:'user_role', column:'user_id', key:'role_id']
version false
}
static constraints = {
}
}
Edit 3: I am now trying to store all test information in the Test domain model and simply choose the Uni name to store as a field in Test, but am getting weird errors when I try this. My new files look like this
class User {
static hasMany = [roles:Role, tests:Test]
Integer userId
static mapping = {
table 'user_data'
id generator: 'assigned', name: 'userId', type: 'long'
userId column: 'user_id'
version false
roles joinTable:[name:'user_role', key:'user_id']
}
static constraints = {
}
}
and
class Test {
static belongsTo = User
Integer testId // primary key
Integer testTypeId
String testTypeName
String testUni
Date testDate
static mapping = {
table 'test'
id generator: 'assigned', name: 'testId', type: 'long'
testId column: 'test_id'
version false
}
static constraints = {
}
}
but now I'm getting the following error when I try to run it Caused by: org.hibernate.MappingException: Missing type or column for column[tests_test] on domain[User] referencing[Test]
Any idea what that's about?
Ok, one issue you have is that you're trying to share the User-to-Test association join table with the Test-to-Unit association. That's not going to work.
Lets look at it in database terms. I'm not an ASCII art expert, so I hope this diagram doesn't make your eyes bleed.
user_data (userId) |---|< (user_id) user_test (test_id) >|---| (testId) test
The diagram above shows the database implementation of the many-to-many association between the User and Test domain classes. You can see that the user_data.userId links to user_test.user_id and user_test.test_id links to test.testId.
Now here's where it starts to get weird. There are two different associations between Test and Uni: a bidirectional one-to-one and a one-to-many. I just don't understand that. But I want to illustrate an important issue with your join tables, so here it is.
test (testId) |---|< (test_id) user_test (uni_id) >|---| (uniId) uni
Because you're using the same join table (user_test) for two different associations you're asking GORM to create a table like this:
USER_TEST
- USER_ID
- TEST_ID
- UNIT_ID
GORM won't do that because join tables are supposed to have only two fields. Not only that, but also you're defining a many-to-many in database terms, and yet a bidirectional one-to-one and a one-to-many in GORM terms. Ouch!
TODO
The first change I recommend is to use a different join table for the Test-Uni association.
Finally got everything working (after a bit of modification in terms of the domain model)
class User {
static hasMany = [roles:Role, tests:Test]
Integer userId
static mapping = {
table 'user_data'
id generator: 'assigned', name: 'userId', type: 'long'
userId column: 'user_id'
version false
roles joinTable:[name:'user_role', column:'role_id', key:'user_id']
}
static constraints = {
}
}
and
class Test {
User user
Integer testId // primary key
String testType
String testUni
Date testDate
static mapping = {
table 'test'
id generator: 'assigned', name: 'testId', type: 'long'
testId column: 'test_id'
version false
}
static constraints = {
}
}
with
class Uni {
Integer uniId // primary key
String shortName
String fullName
static mapping = {
table 'uni'
id generator: 'assigned', name: 'uniId', type: 'long'
uniId column: 'uni_id'
version false
}
static constraints = {
}
}
So now what I'm doing is selecting the university from a drop down tab in my GSP and just saving it in Test as the string testUni. Then, the big change was removing all joinTables between the three and adding User user to Test. I'm still a little fuzzy on why what I was doing before didn't work, but I won't complain about a working app!