Query in Waterline using a model as a criteria - node.js

I just started to work with Waterline and I got question about search for records in a database Mongo using a model as criteria. After some hours of search I couldn't find any satisfactory solution.
First, I have basically 2 model related between themselves:
Post.js
var Post = Waterline.Collection.extend({
tableName: 'Post',
connection: 'default',
attributes: {
url : { type: 'string', required: true, unique: true, lowercase: true },
title : { type: 'string', required: true },
body : { type: 'string', required: true },
author : { type: 'string', required: true },
writeIn : { type: 'string', required: true },
tags: {
collection: 'Tag',
via: 'posts',
dominant: true
},
category: {
model: 'Category'
}
}});
Category.js
var Category = Waterline.Collection.extend({
tableName: 'Category',
connection: 'default',
attributes: {
url: { type: 'string', required: true, unique: true, lowercase: true },
name: { type: 'string', required: true },
posts: {
collection: 'Post',
via: 'category'
}
}});
They are related using Many-to-Many association. The point is that I would like to query a list of posts through a category name.
Something like this:
Post.find().where({category: {url: 'java'}})
Does any of you know how to do this?

Yes you can do this by different way...
Category.find()
.where({url: 'java'})
.populate('posts')

Related

How to set Primary keys in Sails js waterline database relationships

I have been studying relationships with sails JS waterline database from the official documentation. I however been having difficulty understanding how I am supposed to set my foreign keys just like I do in normal mysql relationships.
Please note that I have read the documentation here https://sailsjs.com/documentation/concepts/models-and-orm/associations before asking this question.
Let's say I have a model PersonalInfo.js
module.exports = {
attributes: {
fullName:{
type: 'string',
required: true
},
phone:{
type: 'string',
required: true
},
location:{
type: 'string',
required: true
},
age:{
type: 'integer',
required: true
},
email:{
type: 'string',
required: true
},
gender:{
type: 'string',
required: true
},
userId:{
type: 'integer',
required: true,
}
},
};
And I have another model Archived.js which looks like this
module.exports = {
attributes: {
userId: {
type: 'number',
required: true,
//unique: true,
},
comment:{
type: 'string',
required: true
},
createdBy:{
type: 'number',
required: true
}
},
};
An archived item has a personalInfo. Knowing fully well that both models contain userId property, I want to fetch archived items with the related personalInfo like this, how do I relate the primary keys?
var archived = Archived.find().populate('personal');
By default sails will generate primary key id if you don't specify any.
If you want custom data as your primary key, you can override the id attribute in the model and give a columnName
id: {
type: 'string',
columnName: 'email_address',
required: true
}
You can then find a record using:
await User.find({ id: req.param('emailAddress' });
Reference
In your case, it seems like each archived has a personalInfo. So that's one to one from archived side, but, one to many from personalInfo side. To model these relationships, in sails you can do something like:
personalInfo.js
module.exports = {
attributes: {
fullName:{
type: 'string',
required: true
},
phone:{
type: 'string',
required: true
},
location:{
type: 'string',
required: true
},
age:{
type: 'integer',
required: true
},
email:{
type: 'string',
required: true
},
gender:{
type: 'string',
required: true
},
userId:{
type: 'integer',
required: true,
},
archives: {
collection: 'archived',
via: 'info'
}
},
};
archived.js
module.exports = {
attributes: {
userId: {
type: 'number',
required: true,
//unique: true,
},
comment:{
type: 'string',
required: true
},
createdBy:{
type: 'number',
required: true
},
info: {
model: 'personalinfo' // sails works with small cases internally for models
}
},
};
Once you do this, creating an archive would be:
await Archive.create({
...
// Set the User's Primary Key to associate the info with the archive.
info: 123
});
Now you would finally be able to populate the info while querying.
var archived = Archived.find().populate('info');

Sails js one to one populate conditions not working?

I'm newbie of Sails and I've got a problem with one to one association.
First, I have model User:
module.exports = {
schema: true,
identity : "User",
tableName: "user",
attributes: {
email: {
type: 'email',
unique: true,
required: true
},
password: {
type: 'string'
},
salt: {
type: 'string'
},
merchant: {
model: 'merchant',
defaultsTo: null
},
removed: {
type: 'boolean',
required: true,
defaultsTo: false
}
}
}
And my Merchant model:
module.exports = {
schema: true,
identity : "Merchant",
tableName: "merchant",
attributes: {
name: {
type: 'string',
unique: true,
required: true
},
code: {
type: 'string',
unique: true,
required: true
},
security_key: {
type: 'string',
required: true
},
active: {
type: 'boolean',
defaultsTo: false,
required: true
},
user: {
model: 'user'
}
}
}
So when I need to find records where merchant.active = true, I write this query:
var findUser = User.find(query).populate('merchant', {active: true});
return findUser;
But it was not working at all.
Anyone any ideas to solve this properly?
P.S. my Sails version is: 0.11.1. My DB is MongoDB
First of all, remove defaultsTo from your association attributes. I don't like this :) I don't know if it makes the problem, but in documentation I never see this.
Also you need to execute your query, not just return it. If I take your models' declarations then I can write populate query like this.
var findUser = User.find(query).populate('merchant', {active: true});
findUser.then(function(user) {
console.log('Your user is ' + user);
}).catch(function(error) {
console.log('Your error is ' + error);
});

Sails/Waterline populate does not work in junction table?

Waterline populate gives me an empty collection when I try to populate a junction table (model) with another junction table (model). I'm using many-to-many through relationship as given here:
https://github.com/balderdashy/waterline/issues/705#issuecomment-60945411
I am using sails-mongo adapter for mongolabs.
The example code,
Model user
/user.js
module.exports = {
schema: true,
attributes: {
id: {
type: 'string',
primaryKey: true,
},
student: {
type: 'string'
},
vendor: {
type: 'string'
},
courses: {
collection: 'vendorcourse',
via: 'users',
through: 'usercourse'
},
coursesProvided: {
collection: 'course',
via: 'vendors',
through: 'vendorcourse'
}
}
};
Model Course
/course.js
module.exports = {
attributes: {
id: {
type: 'string',
primaryKey: true,
autoIncrement: true
},
name: {
type: 'string',
required: true
},
description: {
type: 'string'
},
type: {
type: 'string'
},
vendors: {
collection: 'User',
via: 'courseProvided',
through: 'vendorcourse'
}
}
};
Model vendorcourse
module.exports = {
tableName: 'vendorcourse',
tables: ['user', 'course'],
junctionTable: true,
attributes: {
id: {
type: 'string',
autoIncrement: true,
primaryKey: true
},
name: {
type: 'string',
required: true
},
course: {
columnName: 'course',
type: 'string',
foreignKey: true,
references: 'course',
on: 'id',
via: 'vendors',
groupBy: 'course',
required: true
},
vendor: {
columnName: 'vendor',
type: 'string',
foreignKey: true,
references: 'user',
on: 'id',
via: 'coursesProvided',
groupBy: 'user',
required: true
},
users: {
collection: 'user',
via: 'courses',
through: 'usercourse'
}
}
};
Model usercourse
/usercourse.js
module.exports = {
tableName: 'usercourse',
tables: ['user', 'vendorcourse'],
junctionTable: true,
attributes: {
id: {
type: 'string',
autoIncrement: true,
primaryKey: true
},
course: {
columnName: 'course',
type: 'string',
foreignKey: true,
references: 'vendorcourse',
on: 'id',
via: 'users',
groupBy: 'vendorcourse',
required: true
},
user: {
columnName: 'user',
type: 'string',
foreignKey: true,
references: 'user',
on: 'id',
via: 'courses',
groupBy: 'user',
required: true
}
}
};
When I do
usercourse.find().populate('course').exec(function(error,result){
console.log(result);
});
The output is
[{
'id': //some ID,
'course': [] // this is should be populated with the relative record from the vendorcourse model
'user' : //some ID
}]
The course field should contain the record from the vendorcourse model but instead I get an empty collection [].
The same command works when I do
usercourse.find().populate('user').exec(function(error,result){
console.log(result);
});
The output is as expected
[{
'id': //some ID,
'course': //some ID,
'user': [{ //relevent data }]
}]
Am I doing it wrong? OR Is it that sails/waterline doesnt not support a populate from another junction table

Display a list of friends with 3 states on sails.js

I just use sails.js, it is good
I have a problem, please help me.
I have 2 collections, it is create one to many and i want to show list friends with 3 state is defined.
User:
attributes: {
username: {
type: 'string',
required: true
},
firstname: {
type: 'string',
required: true
},
lastname: {
type: 'string',
required: true
},
email: {
type: 'string',
email: 'true',
required: true,
unique: true
},
buddy: {
collection: "Buddy",
via: "buddyOf"
}
}
Buddy:
attributes: {
user_id: {
type: 'string'
},
// 0: no friends
// 1: waiting accept
// 2: Cancel friend
statusBuddy: {
type: 'integer'
},
buddyOf: {
model: 'User'
}
}
I want to search user show 3 button status:
no friends, waiting accept, Cancel friend
Did not try this code, but maybe it could be possible without having 2 models?
identity: 'user',
isFriendedBy: {
collection: 'user',
via: 'friendsWith'
},
friendsWith: {
model: 'user'
},
friendshipStatus: 'integer'

How to do Character wise Search with mongoDB Collection inside model in sails.js

I am newbie to sails and node.js. I am creating a Forum and want to add search function in order to search threads that match with User Search input. My search function need to character wise match the user entered characters with database thread's title. Is there any possible way to do that in sails ? Is it possible to use String distance in sails ?
My models look like as follows,
Forum.js
attributes: {
id: {
type: 'string',
primaryKey: true,
unique: true
},
name: {
type: 'string',
required: true
},
threads: {
collection: 'thread',
via: 'threadOwner'
}
},
Thread.js
attributes: {
id: {
type: 'string',
primaryKey: true,
unique: true
},
creatorUid: {
type: 'string',
required: true
},
title: {
type: 'string',
required: true
},
description: {
type: 'string'
},
threadOwner: {
model: 'forum'
}
},
Try this,
Thread.find({
or : [
{title : { contains:searchKey }},
{description : { contains:searchKey }}
],
threadOwner:forum
}).exec(function(err,matched){
//Your code...
})

Resources