How do I get the count of rows using Bookshelf? - node.js

How can I get the number of rows (without any filter)?
I've tried this User.fetch().count() and User.count(), but I get these errors respectively:
TypeError: User.fetch is not a function
AssertionError: expected { Object (_bitField, _fulfillmentHandler0, ...) } to equal 0
Here's my model:
let bookshelf = require('../config/database');
require('./role');
var User = bookshelf.Model.extend({
tableName: 'users',
role: function() {
return this.hasOne(Role);
}
});
module.exports = bookshelf.model('User', User);

try this:
const knex = require("knex")(require("./knexfile").development);
const Bookshelf = require("bookshelf")(knex);
const User = Bookshelf.Model.extend({
tableName: "user",
idAttribute: "userid"
});
knex.migrate.latest().then(_ => {
User.forge().count().then(ret => {
console.log(ret);
process.exit(0);
});
});
the output should be:
[sombriks#sephiroth sample-knex-bookshelf]$ node index.js
Knex:warning - sqlite does not support inserting default values. Set the `useNullAsDefault` flag to hide this warning. (see docs http://knexjs
.org/#Builder-insert).
3
[sombriks#sephiroth sample-knex-bookshelf]$
please take a look at this repo if you want a more detailed info.

Related

Mongoose query doesn't work with the filter

I'm testing a nodejs snippet to do iteration with my example mongodb collection users. But the query never worked. The full users collection are printed.
The standalone mongodb is setup in EKS cluster.
Why the query {name: "Baker one"} didn't work?
The code is:
const mongoose = require("mongoose");
const url = "mongodb://xxxxxx:27017/demo";
main().catch(error => console.error(error.stack));
async function main() {
// Connect to DB
const db = await mongoose.connect(url);
console.log("Database connected!");
const { Schema } = mongoose;
// Init Model
const Users = mongoose.model("Users", {}, "users");
const users = await Users.find({name: "Baker one"}).exec();
// Iterate
for await (const doc of users) {
console.log(doc);
console.log("users...");
}
console.log("about to close...");
db.disconnect();
}
The users collection:
The execution result:
$ node modify.js
Database connected!
{ _id: new ObjectId("610f512c52fa99dcd04aa743"), name: 'Baker one' }
users...
{ _id: new ObjectId("61193ed9b8af50d530576af6"), name: 'Bill S' }
users...
about to close...
This line could be the culprit (note that the schema has been defined with no fields like Joe pointed out in the comments).
const Users = mongoose.model("Users", {}, "users");
In this case, I had to add StrictQuery option in the Schema constructor to make it work, like so:
const userSchema = new Schema({}, { collection: "Users", strictQuery : false });

How to send paginated result as response after performing find operation in Mongodb?

I have this query to display in a table on frontend so I used paginate which is working fine
tableSchema.statics.getn = (query, options) => {
return mongoose.model(MODEL_NAME).paginate(query, options);
};
But when I am trying to perform search query then I am unable to perform paginate on that. Is there any way to send response as paginated form to all the searched queries
I tried following code
tableSchema.statics.search = query => {
const Id = Number(query);
const isNumeric = value => /^\d+$/.test(value);
if (!isNumeric(query)) {
if (query.includes("#")) {
const regex = new RegExp(query, "i");
return mongoose.model(MODEL_NAME).find({ "recipies.to": regex }).paginate(query);
}
return mongoose.model(MODEL_NAME).find({ "temp.name": query });
}
return mongoose.model(MODEL_NAME).find({ recipies: { Id } });
};
It is throwing me error that paginate is not a function. I tried storing find query result in object then performed paginate still it was not working.
I am using "mongoose-paginate-v2" for pagination
Hi I think you missed to add pagination pluging in model section.
const mongoose = require('mongoose');
const mongoosePaginate = require('mongoose-paginate-v2');
const mySchema = new mongoose.Schema({
/* your schema definition */
});
mySchema.plugin(mongoosePaginate);
const myModel = mongoose.model('SampleModel', mySchema);
myModel.paginate().then({}); // Usage
You need to add mongoosePaginate in model as plugin.
let options = {
sort: { createdOn: 1 },
page: 1,
limit: 10
};
ModelName.paginate({ 'recipies.to': 'value' }, options, function (err, result) {
if (err) {
console.log(err);
} else {
// Here you will get paginate array please console and check
console.log(result);
}

SUM column in bookshelfjs relationship

I want to sum a column in a Bookshelfjs relationship. I have my query set up as
return this.hasMany('MutualFundPortfolio').query().sum('balance');
But I am having this error TypeError: Cannot read property 'parentFk' of undefined any body has any clue how solve this? It seems Bookshelf doesn't support sum
const moment = require('moment');
const Bookshelf = require('../bookshelf');
require('./wishlist');
require('./kyc');
require('./wallet');
const User = Bookshelf.Model.extend({
tableName: 'users',
hasTimestamps: true,
hidden: ['code', 'password'],
toJSON(...args) {
const attrs = Bookshelf.Model.prototype.toJSON.apply(this, args);
attrs.created_at = moment(this.get('created_at')).add(1, 'hour').format('YYYY-MM-DD HH:mm:ss');
attrs.updated_at = moment(this.get('updated_at')).add(1, 'hour').format('YYYY-MM-DD HH:mm:ss');
return attrs;
},
local_wallet() {
return this.hasMany('LocalWallet').query((qb) => {
qb.orderBy('id', 'DESC').limit(1);
});
},
mutual_fund_portfolio() {
return this.hasMany('MutualFundPortfolio').query().sum('balance');
},
global_wallet() {
return this.hasMany('GlobalWallet').query((qb) => {
qb.orderBy('id', 'DESC').limit(1);
});
},
local_gift_card_wallet() {
return this.hasMany('LocalGiftCardWallet').query((qb) => {
qb.orderBy('id', 'DESC').limit(1);
});
},
global_gift_card_wallet() {
return this.hasMany('GlobalGiftCardWallet').query((qb) => {
qb.orderBy('id', 'DESC').limit(1);
});
}
});
module.exports = Bookshelf.model('User', User);
Above is the full user model. I am then getting the value as
return User.where({ id })
.orderBy('id', 'DESC')
.fetch({
withRelated: [
'mutual_fund_portfolio',
'local_wallet',
'global_wallet',
'local_gift_card_wallet',
'global_gift_card_wallet'
]
})
The mutual_fund_portfolio comes out as an empty array.
hasMany performs a simple SQL join on a key. I believe the TypeError: Cannot read property 'parentFk' of undefined error refers to the fact that the table you are referencing here MutualFundPortfolio does not share a key with the table in the model you are using here.
It's not visible above sample but I'm assuming it's something like:
const User = bookshelf.model('User', {
tableName: 'users',
books() {
return this.hasMany('MutualFundPortfolio').query().sum('balance');
}
})
In my hypothetical example the users table has a primary key id column userId that is also in MutualFundPortfolio as a foreign key. My guess is that the error is because MutualFundPortfolio does not have that column/foreign key.

Dealing with models and model methods using Node + Knex + Postgres

I was hoping to get some help. I just started using Postgres with my Node applications and am curious to find out how to go about dealing with models and model methods. What is the best practice when working with Node and Postgres in regards to models and methods? I was looking around and all I could find is something called Objection, but is it absolutely necessary I take that route?
Ideally I would like to have a model.js file for each component but I have not seen them used when dealing with Postgres + Node.
Any help is greatly appreciated. Thanks guys, hope you all had a great Thanksgiving!
Assuming that viewer can understand basic javascript modules and that the codes are mostly self explanatory
This is my model.js file
module.exports = ({
knex = require('./connection'),
name = '',
tableName = '',
selectableProps = [],
timeout = 1000
}) => {
const query = knex.from(tableName)
const create = props => {
delete props.id
return knex.insert(props)
.returning(selectableProps)
.into(tableName)
.timeout(timeout)
}
const findAll = () => {
return knex.select(selectableProps)
.from(tableName)
.timeout(timeout)
}
const find = filters => {
return knex.select(selectableProps)
.from(tableName)
.where(filters)
.timeout(timeout)
}
const update = (id, props) => {
delete props.id
return knex.update(props)
.from(tableName)
.where({
id
})
.returning(selectableProps)
.timeout(timeout)
}
const destroy = id => {
return knex.del()
.from(tableName)
.where({
id
})
.timeout(timeout)
}
return {
query,
name,
tableName,
selectableProps,
timeout,
create,
findAll,
find,
update,
destroy
}
}
This is my controller.js file
const model = require('./model');
const user = model({
name: "users",
tableName: "tbl_users",
});
const getAllUsers = async (req, res, next)=>{
let result = await user.findAll();
res.send(result);
}
module.exports = { getAllUsers }
And Lastly a the connection.js file
const knex = require('knex')({
client: 'pg',
connection: {
host: 'YOUR_HOST_ADDR',
user: 'YOUR_USERNAME',
password: 'YOUR_PASS',
database: 'YOUR_DB_NAME'
},
pool: {
min: 0,
max: 7
}
});
module.exports = knex;

Sequelize queries with node.js

I am trying to determine a better way for my query. I have two tables, one is for recipes, and another is for reviews. Currently, I have two separate queries to find the recipe, and then find the reviews associated with the recipe. Is there a better way I could be doing this?
RecipeController
module.exports = {
viewRecipe: function(req, res) {
var recipeId = parseInt(req.params.id, 10);
var recipeM = {};
var reviewM = {};
db.recipe.find({
where: {
id: recipeId
}
}).then(function(recipe) {
recipeM = recipe.dataValues;
recipeM.ingredients = recipe.ingredients.replace(/\s+/g, '').split(",");
recipeM.instructions = recipe.instructions.split("\n");
}, function (e) {
});
db.review.findAll({
where: {
recipeId: recipeId
}
}).then(function(review) {
console.log(review);
res.render('viewRecipe', { recipe: recipeM, review: review, categories: categoriesMain, title: recipeM.title });
}, function(e) {
});
},
If you are permitted to use ES6 generator, you can apply co.wrap from npm module co
module.exports = {
viewRecipe: co.wrap(function*(req, res) {
var recipeId = parseInt(req.params.id, 10);
var recipeM = {};
var reviewM = {};
var recipe = yield db.recipe.find({
where: {
id: recipeId
}
});
recipeM = recipe.dataValues;
recipeM.ingredients = recipe.ingredients.replace(/\s+/g, '').split(",");
recipeM.instructions = recipe.instructions.split("\n");
var review = yield db.review.findAll({
where: {
recipeId: recipeId
}
});
console.log(review);
res.render('viewRecipe', { recipe: recipeM, review: review, categories: categoriesMain, title: recipeM.title });
}).catch(function(e){
}),
If you have a relationship set up between a recipe and its reviews, I believe you can use Sequelize's include option as follows:
db.recipe
.findById(req.params.id, {
include: [{
model: review
}]
})
.then(function(recipe) {
// your success code
})
.catch(function(err) {
// you error code
});
As far as I know, the include option works as a left join. Also, this should perform better since only one query will be ran on the database.

Resources