I have a pagination in my category service, and I have to return obj with total count of categories and data
But there's can be some parameters. As example, I should return categories that was created by certain user:
async findAll(
{ onlyParents }: ParamsCategoryDto,
user: ITokenPayload | undefined,
): Promise<IFilterRes> {
const categories = await this.prisma.category.findMany({
where: {
user_id: user?.id,
},
});
return {
pagination: {
total: this.prisma.category.count({
where: { // <- duplicate
user_id: user?.id,
},
}),
},
data: categories,
};
}
I should duplicate where in both query. Which is not very nice. Is there any option to do it in one request.
P.S. I can make some var for where, but in this way I lose typification, which I also don't like.
This is my example code to acheive it with a single transaction, no duplicate code and not losing type autocomplete
import { Prisma } from '#prisma/client';
import { PrismaClient } from '#prisma/client'
const prisma = new PrismaClient()
const findAll = async (userId: String) => {
const query: Prisma.categoriesFindManyArgs = {
where: {
user_id: userId,
}
};
const [categories, count] = prisma.$transaction([
prisma.categories.findMany(query),
prisma.categories.count({ where: query.where })
]);
return {
pagination: {
total: count
},
data: categories
};
};
Related
I'm trying to add commodity data to my stockrecord collection and if the commodity name is already in the stockrecord collection I just want to add the quantity of the commodity quantity to my stockrecord quantity.
but even their is existing data the, find method is returning an empty array
This my code
commodity.map(async (e) => {
const data = await new Commodity({
name: e.commodityName,
units: e.units,
quantity: e.quantity,
});
data.donator = donator;
await data.save();
const stock = await StockRecord.find({
name: {
$eq: e.commodityName,
},
});
//console.log(stock);
if (stock.length === 0) {
const record = await new StockRecord({
name: e.commodityName,
units: e.units,
quantity: parseFloat(e.quantity),
});
await record.save();
console.log(record);
} else {
console.log('may sulud');
stock[0].quantity += parseFloat(e.quantity);
await stock[0].save();
}
});
This is my stockrecord model
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const stockRecordSchema = new Schema({
name: {
type: String,
},
units: {
type: String,
enum: \['kg', 'pcs'\],
},
quantity: {
type: Number,
},
});
Array.map does not accept Promises
Try using for (const item of commodity) { //async magic here }
I have an array of strings, I want to map through this array and update my collection with it's values.
This is What I have tried:
if (employees) {
employees.map((employee) => {
Employee.updateOne({ $push: { name: employee.name } })
.then((data) => {
console.log(data);
})
.catch((e) => {
console.log(e);
});
});
}
At the top I am importing my model :
const Employee = require('../../models/employees');
My Model looks like this :
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const EmployeeSchema = new Schema({
name: { type: String },
});
const Employee = mongoose.model('employee', EmployeeSchema);
module.exports = Employee;
My console is logging the next :
{ n: 0, nModified: 0, ok: 1 }
But when i check the database the data is not there and no collection is created.
updateOne has following syntax.
First parameter is condition/filter.
Second parameter is doc to be updated.
Third is options. Where you need to pass upsert to true.
Note: If upsert is set to true then updateOne will create new doc if the filter results empty.
const insertEmployees = () => {
try {
if (employees) {
employees.map(async employee => {
let filter = { name: employee.name }
let doc = { $push: { name: employee.name } }
let options = { upsert: true }
await Employee.updateOne(filter, doc, options)
});
}
} catch (error) {
console.log(error);
}
}
I have 2 schemas
const schema = Schema({
headLine: {
type: String,
required: false
},
availableDays: [{
type: Schema.Types.ObjectId,
ref: AvailableDay
}]
}, {collection: 'providers', timestamps: true});
module.exports = mongoose.model("Provider", schema);
const schema = Schema({
day: {
type: String,
enum: ['Mondays','Tuesdays','Wednesdays','Thursdays','Fridays','Saturdays','Sundays']
},
timeFrom: String,
timeTo: String
}, {collection: 'availableDays', timestamps: true});
module.exports = mongoose.model("AvailableDay", schema);
Then in a route I call to a repository like this
router.get('/', async (req, res) => {
const match = {};
const sort = {};
const options = {};
// Arrange sort
if(req.query.sortBy){
const sortArray = JSON.parse(req.query.sortBy);
sortArray.map(e => sort[e[0]] = e[1] && e[1] === 'desc' ? -1 : 1);
options['sort'] = sort
}
// Get the pagination: limit how many, skip where it starts
if(req.query.limit) {
options['limit'] = parseInt(req.query.limit);
}
if(req.query.skip) {
options['skip'] = parseInt(req.query.skip);
}
const docs = await ProviderRepository.findBy(match, {}, options);
res.status(200).json(docs)
});
So what I need here is to filter providers for an AvailableDay monday and return the docs and count the total docs for pagination. I'm doing something like this without success
const findBy = async (params, projection = "", options = {}, callback) => {
const data = () => {
Provider.find(params, projection, options)
.populate([{path: 'user', match: {gender: 'F'}}]).exec((error, e) => {
if (error) {
console.log('error:', error)
return {error: error}; // returns error in json
}
return e.filter(i => i.user);
});
};
const total = await Provider.countDocuments(params).exec();
return {data(), total}
}
Thanks in advance
Use mongoose-aggregate-paginate-v2 and update your schema. If you use that package then you have to convert your queries from populate to aggregate style.
STEP 1: Update schema. Sample Schema:
const mongoose = require('mongoose');
const mongoosePaginate = require('mongoose-aggregate-paginate-v2');
const Schema = mongoose.Schema;
let definition = {
headLine: {
type: String,
required: false
},
availableDays: [{
type: Schema.Types.ObjectId,
ref: AvailableDay
}]
};
let options = {
collection: 'providers'
};
let providerSchema = new Schema(definition, options);
providerSchema.plugin(mongoosePaginate);
module.exports = mongoose.model('providers', providerSchema);
STEP 2: Update controller. Sample code in controller:
router.get('/', async (req, res) => {
const match = {}
const sort = {
// Fill it based on your sort logic.
}
const paginateOptions = {
page: req.query.page, // Page number like: 1, 2, 3...
limit: req.query.limit // Limit like: 10, 15, 20...
};
ProviderRepository
.findBy(match, {}, sort, paginateOptions)
.then(() => {
res.status(200).json(docs)
})
.catch(() => {
res.status(HTTP_ERROR_CODE).json({ "error": "Your error message" })
})
});
STEP 3: Update manager. Sample code in manager:
const findBy = (match, projection, sort, paginateOptions) => {
if (!paginateOptions) {
paginateOptions = {
pagination: false
};
}
let providerAggregate = providerSchema.aggregate([
{
$lookup: {
from: "availableDays",
let: { days: "$availableDays" },
pipeline: [
{
$match: {
$expr: {
$in: ["$$availableDays", "$day"]
}
}
}
],
as: "availableDays"
}
},
{
$lookup: {
from: "users", // I dont know the collection name
let: { user_id: "$user" }
pipeline: [
{
$match: {
"gender": 'F',
$expr: {
$eq: ["$_id", "$$user_id"]
}
}
}
],
as: "users"
}
}
{ $sort: sort }
]);
return providerSchema
.aggregatePaginate(providerAggregate, paginateOptions)
.then(res => {
return res;
})
.catch(err => {
throw err;
});
};
I have two models in my aplication, Delivery and DeliveryProblem.
DeliveryProblem has a PK (delivery_id) from Delivery:
static associate(models) {
this.belongsTo(models.Delivery, {
foreignKey: 'delivery_id',
as: 'delivery',
});
}
I need select all Deliveries that have a Delivery Problem.
In my Controller, a have the follow method:
async index(req, res) {
const response = await DeliveryProblem.findAll({
order: ['id'],
attributes: ['delivery_id'],
});
// Filter all Deliveries with problem
const ids = [...new Set(response.map((x) => x.delivery_id))];
const deliveries = Delivery.findAll({
where: , // <<< How can I filter ?
order: ['id'],
});
return res.json(deliveries);
}
const Sequelize = require('sequelize')
const Op = Sequelize.Op
...
// Filter all Deliveries with problem
const ids = [...new Set(response.map((x) => x.delivery_id))];
const deliveries = Delivery.findAll({
where: {
id: {
[Op.in]: ids
}
},
order: ['id'],
});
like js code
when I do this
it will query up to 1000 times,
can it query once?
const promises = idList.map(async id => {
const query = new Parse.Query("results");
query.equalTo("id", id);
query.descending("createdAt");
query.first()
});
const prPool = await Promise.all(promises);
You need to use aggregate. It would be something like this:
const pipeline = [
{ match: { id: id } },
{ sort: { createdAt: -1 } },
{ group: { objectId: '$id', lastCreatedAt: { $first: '$createdAt' } } }
];
const query = new Parse.Query('results');
const prPool = await query.aggregate(pipeline);