Database schema with sails.js and sails-postgresql - node.js

Is there any way to set database schema with sails-postgresql waterline adapter?
By default postgres adapter allways choose default public schema in database but I want to connect it to another schema.
For example I have database dev, schema test in database dev and table users in schema test.
Now I want to select all data from table users, in sql syntax I can simply write:
SELECT * FROM test.users
How to make it work in sails ?
When I write a model that uses postgres adapter, method Users.find() will look for the table users in default public schema. I want to change it to look in schema test without interactions with my postgres database.
Is it possible?

There is support for this, although it is as-yet undocumented. You can set the schema name for a model using the meta.schemaName property, eg:
module.exports = {
tableName: 'users',
meta: {
schemaName: 'test'
},
attributes: {
...
}
};
Update
It turns out this functionality was essentially broken for several versions, but it has been revamped and released in Sails-Postgresql v0.11.0. The syntax is the same as above. The main caveat is that it will not work with multiple Waterline models sharing the same tableName.

It appears that this is a bit buggy on the latest 1.0.3 version, but I found a way to accomplish it, by doing :
postgresql: {
adapter: require('sails-postgresql'),
url: 'postgresql://postgres:blablabla#localhost:5432/simplerp',
schemaName: 'radius',
}
On your config/datastores.js file.
Peace, out!

Related

Is there a way to access mongodb node.js driver functionality while still using mongoose for schema definition?

What I am really trying to do is to make indexes for filtering and string matching of documents based on their property values.
I know that mongodb has built in operators such as $text that are very helpful with this sort of functionality.
I'm not sure how to access these operators while using mongoose, or if there are any methods i need to use to access them.
I want to use mongoose to still define schema and models but need the functionality of native mongodb.
Is this possible?
Below are my views, Please add if I miss anything or if something needs to be modified or well-explained :
1. You will still be able to use mongoDB's native functionalities on using Mongoose models.
2. Mongoose is a kind of wrapper on top of native mongoDB-driver.
3. It would be very useful if you want to have schema based collections/data.
4. Additionally it would provide few more features than native mongoDB's driver. You might see few syntax differences between those two.
5. Few examples like `.findByIdAndUpdate()` & `.populate()` are mongoose specific, which has equivalent functionalities available in mongoDB driver/mongoDB as well.
6. In general it's quiet common to define mongoose models and use those over mongoDB's functionality in coding(As in node.js - You would write all of your same DB queries on Mongoose models, queries that you execute in DB).
Point 2 :
Mongoose is an object document modeling (ODM) layer that sits on top of Node's MongoDB driver. If your coming from SQL, it's similar to an ORM for a relational database.
Point 3 :
In code if you're using mongoose models to implement your write queries, unless you define a field in model - it wouldn't be added to DB though you pass it in request. Additionally you can do multiple things like making a field unique/required etc.. it's kind of making your mongoDB data look like schema based. If your collections data is more like random data(newsfeed kind of thing where fields are not same for each document & you can't predict data) then you might not care of using mongoose.
Point 6 :
Let's say you use mongo shell or a client like mongo compass/robo3T and execute a query that's like this :
db.getCollection('yourCollection').find(
{
$text: {
$search: 'employeeName',
$diacriticSensitive: false
},
country: 'usa'
},
{
employee_id: 1,
name: 1
}
).sort({ score: { $meta: 'textScore' } });
you would do same on mongoose model(As yourCollectionModel is already defined) :
yourCollectionModel.find(
{
$text: {
$search: 'employeeName',
$diacriticSensitive: false
},
country: 'usa'
},
{
employee_id: 1,
name: 1
}
).sort({ score: { $meta: 'textScore' } });
You would see key functionality difference more on writes rather than reads while using mongoose, though all the above is not about performance - If you ask me, I can say you might see much performance gains using mongoose.
Ref : Mongoose Vs MongoDB Driver

Create dynamic collection in MongoDB using Sails.js

I am working with SailsJs+MongoDB API. I have to create New colletion in mongoDB .Name of colletion will be in request Parameter.
example:
Suppose I want to create 'Users' collection in 'mongoDbDatabase' database
by following request.
{
"collectionName" : "Users",
"dbName" :"mongoDbDatabase"
}
Now is there any way to create dynamic collection in mongoDB using req.param('collectionName) variable ?
To use all the tools that Sails provides, you have to add code (before you start your app) for each Model / Collection you are planning to interact with. As a result, creating a collection dynamically will mean you can't take advantage of the whole data - framework sails provides.
Are you sure you need a dynamic collection? Why not a defined collection differentiated by attributes?
If you really need to do this from Sails, it looks like you can get access to the underlying raw mongo database:
var db = AnyModel.getDatastore().manager; // the database will be as defined in config/models.js or config/connections.js
var collectionName = 'Widgets';
db.createCollection(collectionName);
// note, even if this works, something like 'Widgets.find' will not.

how to update records in association though sequelize in node js?

we are trying to update records in association though sequelize but its only updating the records of model on which it is fired or direct model no associated model affected by the query .
any pathway to perform this
return db.product.findById( 75759,{
include: [
{
model: db.productDescription
}
]})
.then(product => {
var rahulpro = {};
Object.assign(rahulpro,product);
// console.log(rahulpro.product_description.description);
rahulpro.name = "44444";
rahulpro.product_description.dataValues.description = "rahul";
product.updateAttributes(rahulpro);
});
What do you expect to happen?
we want to update data of description model
What is actually happening?
Nothing changed database of description
Database version: mysql 5.7
Sequelize version: 4.8.3
I've had a very similar issue using Sequelize. After hours of looking into it, I've seen there is no great way to handle data attached to through tables.
For what you're trying to do, you'll have to perform 2 queries, find the product instance from your product table, and then query the product_description table where description.product_id === product.id.
Then write the changes to the description instance, then to the product instance.
This was a shortcoming of ORM's in my project, and for more complex queries we started using raw sequel because it gave us the ability to do things like this.

Associations in Sequelize migrations

My app currently uses the Sequelize sync() method to create the database, and I want to change it to use the migrations system.
One of my model has belongsTo() associations with other models, and I don't really know how to make the initial migration code for these associations.
Do I have to manually create the foreign key with SQL queries, or is there some methods available?
Case 1: Database initialization
If your purpose is to add relations during initialization of database structure it is better to just use sync method instead of manually adding them using migrations. If your models are properly designed and have relations defined, they will be created automatically during execution of sync method.
Take a look at sequelize express example. In models directory you have three files:
index.js - which includes all models
task.js - task model
user.js - user model
Look at task.js content, starting from line 7 the following code creates a relation between User and Task models:
classMethods: {
associate: function(models) {
Task.belongsTo(models.User, {
onDelete: "CASCADE",
foreignKey: {
allowNull: false
}
});
}
}
If you correctly prepare your relations in model files, sync will create the foreign keys for you. Migrations aren't necessary in this case.
I encourage you to read the whole express-example readme.md and browse repository files to see how the things work with express and sequelize.
Case 2: Database structure migration
In case you already have some data which you want to keep, you need to use migration script, because the only way for sync to restructure your database is to destroy it completely alongside with all its data.
You can read about basic migrations in the sequelize docs. Unfortunately docs do not cover creating a relation. Let's assume you want to create the following relation: User belongs to Group. To create column on the user side of relation, you may use addColumn method.
queryInterface.addColumn(
'user',
'group_id',
{
type: Sequelize.INTEGER,
allowNull: true
}
)
Unfortunately there isn't a nice function (yet) to create the foreign key constraint for you, but you can do it manually using sequelize query method. Postgresql example:
queryInterface.sequelize.query("ALTER TABLE user
ADD CONSTRAINT user_group_id_fkey FOREIGN KEY (group_id)
REFERENCES group (id) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE;");
Edit: Added database structure migration case
Adding this as an answer instead of a comment (not enough rep) for #aryeh-armon answer above. It's the table name that you need to make sure exists rather than the model name. i.e. if your model is named Job and your db table is named Jobs then the migration would look look like this instead.
jobId: {
type: Sequelize.INTEGER,
references: {
model: "Jobs",
key: "id"
}
},
you can add references to the migrations
Exmaple:
user_id: {
type: Sequelize.BIGINT,
references: {
model: "users",
key: "id"
}
},
Just make sure the model you are referencing exists.
After lots of searching, I found a couple of blog posts explaining what I wanted to do. The first one no longer exists, and here's the second one
Apparently it's not really the common way to do it, but it seems more logical to me. If you want to use only the migrations, you have to use SQL queries to create the initial migration.
But anyway, I think that ezpn is right about creating the initial database with sync, and then migrate. It seems easier than using umzug and only use migrations.

Using sequelize.js to interface against existing database?

I'm currently working in a project where our Node.js server will perform a lot of interactions against an existing MySQL database. Thus I'm wondering if Sequelize is a good library to interface the database. From what I've read about it, it is most often used as a master of the database. But in my case it will only have select,insert,delete access and not access to modify and create tables and so on. Does Sequelize support this method of interaction with a database?
If Sequelize does indeed work good for this, what settings do i need to disable to not run into much trouble? After reading their documentation i could not find any global settings to turn it into a simple interface tool. Timestamps and such could be disabled on table definition but not globally what I saw. Any input is greatly appreciated.
There are a lot of questions in this post, I'll try to answer them all:
Disable timestamps globally:
new Sequelize(... ,{
define: {
timestamps: false
}
});
You can pass any define options to the sequelize constructor and they will be applied to all calls to sequelize.define
Mapping to an existing database
I'll try to describe some common cases here:
I want my model to have a different name to my database table:
sequelize.define('name of model', attributes, {
tableName: 'name of table'
});
My database columns are called something different than the attributes in my model:
sequelize.define('name of model', {
name_of_attribute_in_model: {
type: ...
field: 'name of field in table'
}
});
My primary key is not called id:
sequelize.define('name of model', {
a_field_totally_not_called_id: {
primaryKey: true // also allows for composite primary keys, even though the support for composite keys accross associations is spotty
autoIncrement: true
}
});
My foreign keys are called something different
X.belongsTo(Y, { foreignKey: 'something_bla' });
disclaimer: I am a sequelize maintainer :). Overall I think we have pretty good support for working with legacy DBs. Feel free to ask more questions here or on irc://irc.freenode.net#sequelizejs

Resources