Why is sails.js limiting responses by default? - node.js

I created a default sails.js install with all default options on top of a simple mysql database. Currently, I have a table with 91 records.
I have an ionic front end that loads the list in that table, but it's displaying 30 records.
I used postman to hit the sails.js url (http://localhost:1337/list) and that is showing 30 records returned).
While it's a duplicate effort, I hit the url (http://localhost:1337/list) directly in a browser and it still returns 30 records.
Is there a default to how many records sails.js will return?
If so, how do I remove this default so sails.js will return all the results rather than a subset? I don't want to paginate, I want the full list.
PS I have checked the sails.js model I created to verify I don't have any funky limiting stuff and it's uber barebones.
I have no custom code and the entire sails.js install is the default minus the db connection, the skeleton controller, and the models.
Here's my model:
module.exports = {
identity: 'List',
attributes: {
id: {
type: 'integer',
primaryKey: true
},
name: {
type: 'string',
unique: true,
required: true
},
user: {
type: 'integer'
}
}
};

You are using blueprints for find action.
Go inside config/blueprints.js file and check all comments...
There you will find:
/****************************************************************************
* *
* The default number of records to show in the response from a "find" *
* action. Doubles as the default size of populated arrays if populate is *
* true. *
* *
****************************************************************************/
// defaultLimit: 30
Change it as you prefer.

Related

Best way to programmatically add tables to node and express app with Sequelize

I have been doing some research on this for a bit but can't seem to find the right answer. I am building a personal bugetting application with node, Express and Sequelize. In order to give users as much flexibility as possible, I want the app to dynamically generate tables for user budgets. Users can create as many budgets as they want, and add up to 10 or 12 columns. I was thinking of using a Sequelize raw query, but dynamically generating the query is messy and I'm not sure it's very good practice. Should I use a migration and the umzug library? The thing is I'm still pretty new to server side development and databases so I just need a bit of guidance on this. Here is my current raw query. I haven't tested it yet as I have been building out other core components of the app.
/* Handle dynamic budget table creation and queries */
const Db = require('./lib/Db.js');
module.exports = class Budget extends Db
{
/**
* Create a new budget table
* #param {String} name - budget name
* #param {Object} columns - object of column names and their values
* #param {String} user - user name
* #param {Number} userId - user id
*/
async createNewBudget(name, columns, user, userId)
{
let query = `CREATE TABLE ${name}_budget (`;
for (let key in columns) {
query += `${key} NUMERIC, `;
}
query += ")";
await this.db.sequelize.query(query);
let insert = `INSERT INTO ${name}_budget(`;
for (let key in columns) {
insert += `${key}, `;
}
insert += ") VALUES (";
for (let key in columns) {
insert += `${columns[key]}, `;
}
insert += ")";
await this.db.sequelize.query(insert);
}
}
The Db class is a simple class that makes available the sequelize instance:
/* Base class for all classes interacting with the database via raw queries */
module.exports = class Db
{
constructor()
{
this.db = require('../models/index.js');
}
}
I have these files in my lib directory. I just have a feeling that the way I'm going about this isn't that good. Any helpful suggestions would be greatly appreciated.
I'm a little curious as to why you want a user to be able to create new tables... I think you should be using migration to setup your original database, and think it through to the point where users have id's, then you have a user_budget table that is a many to many connection to budget an array of options after that, database design does take some planning but it is not rocket science and if/when you don't get it right, it's not too hard to change... postgres, mySQL etc are great at handling scads of rows efficiently and many relationships, but i think you might be creating a bunch of technical debt and non-scalable solution to create new tables for new budgets, that is unnecessary with an RDBMS. You are creating a new table for something that could just be a couple rows in a well designed DB
We can define the model in one file, say models/budget.js:
module.exports = function (sequelize, DataTypes) {
const Budget = sequelize.define('budget', {
id: {
type: DataTypes.UUID,
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
},
category: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
},
name: {
type: DataTypes.STRING,
allowNull: true,
defaultValue: null,
},
...,
version: {
type: DataTypes.INTEGER,
defaultValue: 0,
allowNull: false,
},
}, {
version: true,
paranoid: true
});
return Budget;
};
Then create a "migrations" file which loads the model into the DB:
'use strict';
const models = require('../models');
module.exports = {
up: function (queryInterface) {
return queryInterface.createTable(models.Budget.tableName, models.Budget.rawAttributes);
},
down: function (queryInterface) {
return queryInterface.dropTable(models.Budget.tableName);
},
};

How to search single field in mongoDB using querymen?

Hi I'm currently developing a REST API using this generator.
https://github.com/diegohaz/rest?fbclid=IwAR3FwvhJuKpAtCrywOIRkpts8ZvZ_36Gk9b8ksSv2_MEgFtJnl4G7QZvGNI
But I'm kind of new with the MEAN stack environment especially mongoDB.
I just want to ask how to use the search query parameter described in this auto generated document of my project.
https://www.screencast.com/t/4wR7qyxj5ZP
I'm trying to search all the menu by list_id
for MYSQL something like this.
Select * from menu where list_id = '123';
So this generated REST API application is using querymen for search query. I already tried www.domain.com/menus?q={list_id:"1"}, www.domain.com/menus?q={"list_id":"1"} but none of this works it only shows empty results.
Here's my the router part of the code.
/**
* #api {get} /menus Retrieve menus
* #apiName RetrieveMenus
* #apiGroup Menu
* #apiUse listParams
* #apiSuccess {Object[]} menus List of menus.
* #apiError {Object} 400 Some parameters may contain invalid values.
*/
router.get('/',
query({ limit: { max: 1000 } }),
index)
I'm answering my question just in case someone has the same problem. So I figured out that I just need to include a custom schema in the query parameter so instead of
router.get('/',
query({ limit: { max: 1000 } }),
index)
It is now like this.
query({
list_id: {
type: String,
paths: ['list_id']
},
limit: { max: 1000 }
}),index)
You can also change the String to Regexp if you want.

executing direct query in controller in loopback

I have started working in loopback 4.I have created a default CRUD controller with basic CRUD operations which can get 'the table data', 'the table record for particular id' etc.. what I need now is I want to execute my own query for this table. How to write a query in controller and execute it?
/* below is the default function to get table data*/
#get('/customers', {
responses: {
'200': {
description: 'Array of customers model instances',
content: {
'application/json': {
schema: {type: 'array', items: {'x-ts-type': Customers}},
},
},
},
},
})
async find(
#param.query.object('filter', getFilterSchemaFor(Customers)) filter?: Filter,
: Promise<Customers[]> {
if (limit > 100) limit = 100; // your logic
return await this.CustomersRepository.find(filter);
}
the type of code I want is,
Execute(dataset, sqlstatement); //is that available?
Support for executing raw database queries was added recently by the pull request #2681, this functionality is provided by Repository method execute.
Please note that they query format is connector-specific. For example, if you are using MySQL database, then you can write the following query:
await this.CustomersRepository.execute(
// the query template, use "?" for variables to AVOID SQL INJECTIONS ATTACKS!
'SELECT TOP ? * FROM CUSTOMERS',
// the values to use for variables
[limit]);

Set default value to a model(Sails.js)

I am starting to learn Sails.js and I want to know if there is a simpler way to set the default value in a model from a session variable? I am using Waterlock to do authentication and setting the user_id in a session variable like req.session.user_id. I have a message model, I want to default the 'from' field to this session variable. Is there a way to do this in Sails.js?
If you are using Sail's default ORM, Waterline, then model attributes have a defaultsTo option. The supplied value may be a function. You can look at the waterline documentation.
Sample Model
module.exports = {
attributes: {
description: {
type: 'string',
defaultsTo: 'No description.'
},
email: {
type: 'email',
required: true,
unique: true
},
alias: {
type: 'string',
defaultsTo: function(){
return this.email;
}
},
}
};
If the supplied value is a function, then the call to this function is bound to the values in the create.
For Model.create(values)..., if alias is null/undefined, then alias = defaultsTo.call(values) is used to get the value for alias.
So to use req.session.user_id you may have to include it during create.
Model.create({session: req.session,...}). I am not really sure, since I do not use Waterlock. And I'm not don't think this is the best way to go about it.
From my experience these extra values are ignored when using adapters such as sails-mysql, but if you are using sails-disk for development, then you might see that these extra values are persisted. You may want to delete them before you persist.
beforeCreate: function(values, cb){
delete values['session'];
cb();
}

Execute query in Mongoose schema validation

Im trying to setup my MongoDB design in such a way that there is a projects collection, and a people collection. The Project model schema contains a _people item, which references the People model. (As opposed to the People model having a field to reference the project he/she belongs to. It needs to be like this)
I need to run a validation whenever a new document is created in the people container, that there can be only one manager per a project. This would be very easy if it was possible for me to execute a query for the elements validation in the schema, but I don't believe thats possible...
Heres the schema for the People model currently:
const peopleSchema = new Schema( {
name: {
type: Schema.Types.String,
required: true,
minlength: 3,
maxlength: 25,
trim: true,
select: true
},
isManager: {
type: Schema.Types.Boolean,
default: false,
validate: {
validator: function ( v ) {
// How can I check if there are any existing `people` documents with the
// `isManager` set to true, which are referenced by the same project.
// If I can return a promise from here, then I can just execute a query and verify the results
},
message: 'There can be only one manager per each group'
}
}
})
As you can see in the isManager.validate.validator function, I noted that if this documents isManager is set to true, I need to find a way to check that there isn't already a person document referenced by the same project that is also a manager.
Knowing which project is referencing this document isn't an issue, I will have that somewhere, I just need to know how to run a query.. is that possible?
I was able to accomplish the desired effect by using Mongooses Middleware functionality. Setting up the validation inside the pre-save hook worked just fine

Resources