express mongoose : getting aggregate returns empty array - express

Dears,
I'm having trouble in getting back mongoDB aggregation, using mongoose.
The query in MongoDB is sending back data, but the call from mongoose always returns empty array
UPDATE
I found the fix, I have to add a 3rd parameter when setting the model
const RawData = mongoose.model('rawdata', rawDataSchema, 'rawdata');
Here is the code
Schema rawdata.js
import mongoose from 'mongoose';
const rawDataSchema = new mongoose.Schema({
Email: String,
Nb: Number,
Licences: String,
Licence_ret: String,
Pays: String,
Share: String,
Pack: String,
Quota_in_MB: Number,
Webmail_Ext: Number, });
const RawData = mongoose.model('rawdata', rawDataSchema);
export default RawData;
index.js - edited after first feedbacks
import express from 'express';
import mongoose from 'mongoose';
import RawData from 'rawdata'
const app = express();
app.get('/test', async (req, res) => {
const data = await RawData.aggregate(
[
{ "$group": { _id: { license: "$Licence_Carrefour" }, count: { $sum: 1 } } },
{
$project: {
_id: 0,
License: "$_id.license",
count: 1
}
}
]);
console.log('data', data)
res.send('hello')
});
(async () => {
await mongoose.connect(dbURI, { useNewUrlParser: true }, err => {
if (err) console.log('\x1b[31m%s', 'DB is not connected');
console.log('connected to database ');
});
app.listen(APP_PORT, () => console.log('app up'));
})();

Related

how to handle image upload in the mern stack using multer?

Im creating a MERN stack application and in the react front end, i intend to have a form to add a product, the form is going to have a lot of inputs including an image upload option. I want to know how to handle the image upload from the express side using Multer. i have used their documentation but im not sure whether the code i wrote is correct. I also haven't created the front end yet, so i am currently using postman to test the api. How do i test whether the image upload functionality is working using postman? I would be posting the code i have written so far for context.
Product model:
const mongoose = require('mongoose')
const ProductSchema = new mongoose.Schema({
name:{
type: String,
required: [true, 'please provide a product name'],
maxlength: 20,
minlength: 3
},
category: {
type: String,
required: [true, 'please provide a category'],
maxlength: 20,
minlength: 3
},
quantity: {
type: Number,
required: [true, 'please provide the quantity']
},
price: {
type: Number,
required: [true, 'please provide the price']
},
description: {
type: String,
required: [true, 'please provide the description'],
trim: true
},
image: {
type: String
},
createdBy: {
type: mongoose.Types.ObjectId,
ref: 'User',
required: [true, 'Please provide the user'],
}, },
{ timestamps: true } )
module.exports = mongoose.model('Product', ProductSchema)
file upload.js:
const multer = require('multer')
const { v4: uuidv4 } = require('uuid')
const storage = multer.diskStorage({
destination: function(req, file, cb) {
cb(null, '../uploads')
},
filename: function(req, file, cb){
cb(null, uuidv4() + '-' + Date.now() + path.extname(file.originalname) )
}
})
const fileFilter = (req, file, cb) => {
const allowedTypes = ['image/jpeg', 'image/jpg', 'image/png']
if(allowedTypes.includes(file.mimetype)) {
cb(null, true)
}else(
cb(null, false)
)
}
const upload = multer({storage, fileFilter})
module.exports = upload
Product router:
const express = require('express')
const router = express.Router()
const upload = require('../utils/fileUpload')
const {getAllProducts, createProduct, getProduct, updateProduct, deleteProduct} = require('../controllers/products')
router.route('/').post(upload.single('image'), createProduct).get(getAllProducts)
router.route('/:id').get(getProduct).patch(updateProduct).delete(deleteProduct)
module.exports = router
Product controller:
const Product = require('../models/Product')
const { StatusCodes } = require('http-status-codes')
const { BadRequestError, NotFoundError } = require('../errors')
const createProduct = async (req, res) => {
req.body.createdBy = req.user.userId
const product = await Product.create({...req.body, image: req.file})
res.send('create Product')
}
const getAllProducts = async (req, res) => {
res.send('get All products')
}
const getProduct = async (req, res) => {
res.send('get product')
}
const updateProduct = async (req, res) => {
res.send('update product')
}
const deleteProduct = async (req, res) => {
res.send('delete product')
}
module.exports = {
getAllProducts, createProduct, getProduct, updateProduct, deleteProduct
}
You can change the parameter type to file from postman to try uploading files when sending a request :

Connect.sid not in cookie even with withCredentials:true in axios (rtk-query / react-native)

I am using rtk-query and an axiosbasequery set up like this:
export const apiSlice = createApi({
reducerPath: "apiSlice",
baseQuery: baseQueryWithErrorHandling,
endpoints: (builder) => ({
//endpoints
})
})
baseQueryWithErrorHandling just logs out the app in the event of a 401 error.
export const baseQueryWithErrorHandling = async (
args: IBaseQuery,
api: BaseQueryApi,
extraOptions: {}
) => {
const result = await rawBaseQuery(args, api, extraOptions);
if (result.error) {
if (result.error.status == 401) {
api.dispatch(logOut());
return result;
}
}
return result;
};
rawbaseQuery:
export const rawBaseQuery: BaseQueryFn<
IBaseQuery,
unknown,
FetchBaseQueryError
> = async ({ url, method, data, params }, api, extraOptions) => {
const query = axiosBaseQuery({
baseUrl: Globals.URLS.BASE_URL,
headers: (headers) => {
headers["Accept"] = "application/json";
headers["Content-Type"] = "application/json";
return headers;
},
});
return query({ url, method, data, params }, api, extraOptions);
};
And finally, the actual axios query. I put withCredentials in two spots.
import type { BaseQueryFn, FetchBaseQueryError } from "#reduxjs/toolkit/query";
import axios from "axios";
import type { AxiosRequestConfig, AxiosError } from "axios";
import Globals from "../globals/Globals";
axios.defaults.withCredentials = true; // Here (Spot #1)
export interface IAxiosBaseQuery {
baseUrl?: string;
headers?: (headers: { [key: string]: string }) => { [key: string]: string };
}
export interface IBaseQuery {
url: string;
params?: { [key: string]: string | number | Boolean };
method: AxiosRequestConfig["method"];
data?: AxiosRequestConfig["data"];
error?: {
status: number;
data: unknown;
};
}
export const axiosBaseQuery = ({
baseUrl = "",
headers,
}: IAxiosBaseQuery): BaseQueryFn<
IBaseQuery,
unknown,
FetchBaseQueryError
> => async ({ url, method, data, params }, api, extraOptions) => {
try {
const result = await axios({
url: params?.skipBaseURL ? url : baseUrl + url,
method,
...(params && { params: params }),
...(headers && { headers: headers({}) }),
...(data && { data: data }),
responseType: "json",
withCredentials: true, // And here (Spot #2)
});
return { data: result.data };
} catch (axiosError) {
let err = axiosError as AxiosError;
// error logic
}
};
Yet, it seems sometimes the cookie is passed, and sometimes not.
Here's my flipper log of a successful request with a connect.sid in the cookie.
Yet, the next request results in an error because the session id doesn't exist.
Any suggestions? I've been having this problem for a week.

(redis-om & fastify) this.writeEntity is not a function

I'm learning to use the Redis for my backend database and I would like to try using redis-om for fastify not sure whether they are compatible or not, but I got error.
I use service of app.redislabs.com
I don't know what I just messed up? And how can I fix the problem?
server.js
const { createCar, createIndex } = require("./redis");
app.post("/add", async (req, res) => {
await createIndex();
const { make, model, image, description } = req.body;
const data = { make, model, image, description };
await createCar(data);
res.code(200).send('ok');
});
const PORT = 5000;
app.listen(PORT, function (err) {
if (err) {
app.log.error(err);
process.exit(1);
}
});
redis.js
const { Client, Entity, Schema, Repository } = require("redis-om");
const client = new Client();
const connect = async () => {
if (!client.isOpen()) {
await client.open("redis://default:password#localhost:6379");
} else {
console.log("CONNECTED");
}
};
class Car extends Entity {}
let schema = new Schema(
Car,
{
make: { type: "string" },
model: { type: "string" },
image: { type: "string" },
description: { type: "string" },
},
{ dataStructure: "JSON" }
);
const createCar = async (data) => {
await connect();
const repository = new Repository(schema, client);
const car = repository.createEntity(data);
const id = await repository.save(car);
return id;
};
const createIndex = async () => {
await connect();
const repository = new Repository(schema, client);
await repository.createIndex();
};
module.exports = {
createCar,
createIndex,
};
My JSON Body
You cannot call new on Repository. This is a breaking change I introduced in version 0.2.0 of Redis OM. There are a couple of others that are documented in the CHANGELOG.
Call const repository = client.fetchRepository(schema) instead, as shown here. Unfortunately, there are some videos and blogs that have the older syntax and so this crops up from time to time.
Thanks for using my library!

findOne is not a function

I am trying to create a model using Sequelize and mysql db.I am trying to post to '/students/register' it keeps giving me an error saying findOne is not a function. I tried requiring my sql but it's not working ..I also tried a different function like findAll and still not working.what seems to be the problem
const Sequelize = require('sequelize');
module.exports = function (sequelize, Sequelize) {
const Stundet = sequelize.define(
'student', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: Sequelize.STRING
},
email: {
type: Sequelize.STRING
},
password: {
type: Sequelize.STRING
},
created: {
type: Sequelize.DATE,
defaultValue: Sequelize.NOW
}
}, {
timestamps: false
});
module.exports = Stundet;
}
routes
const Student_Info = require("../models/students")
student.post('/register', (req, res) => {
const dataToday = new Date()
const studentData = {
name: req.body.name,
email: req.body.email,
password: req.body.password,
created: dataToday
}
Student_Info.findOne({
where: {
email: req.body.email
}
})
.then(student => {
if (!student) {
bcrypt.hash(req.body.password, 10, (err, hash) => {
studentData.password = hash
Student_Info.create(studentData)
.then(student => {
res.json({
status: student.email + 'registered'
})
})
.catch(err => {
res.send('error' + err)
})
})
} else {
res.json({
error: 'Student already registered'
})
}
})
.catch(err => {
res.send('error' + err)
})
})
module.exports = student;
When you use module.exports, you should return Stundet. You already export the whole function. And I think you should pass DataTypes instead of Sequelize.
Something like this:
module.exports = function (sequelize, DataTypes) {
const Stundet = sequelize.define(
//...
return Stundet;
}
So in your route in order to use your model:
const Sequelize = require('sequelize');
const DataTypes = sequelize.DataTypes;
let sequelize = new Sequelize(...);
const Student = require('../models/students')(sequelize, DataTypes);
I suspect that your Student_Info is null. Does you application successfully connect to the database? It helps to log... e.g.
sequelizeDB
.authenticate()
.then(() => {
console.log('Yes! DB Connection);
...
})
.catch(err => {
console.error('No! Unable to connect to DB', err);
});
... and IMHO the code reads better when you name the DB instance something other than "sequelize".

How to get socket.io to recognize when model has been updated

I'm relatively new to MEAN/Mongoose/socket.io and am missing something that seems like it'd be basic, but regardless, it's keeping me from moving forward.
I'm keeping track of a group's meetings and have the following Schema:
'use strict';
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var ScheduleSchema = new Schema({
description: String,
meetingPlace: String,
office: String,
start: { type: Date, default: Date.now },
end: { type: Date, default: Date.now },
participants: [{
type: Schema.Types.ObjectId,
ref: 'User'
}],
author: {
type: Schema.Types.ObjectId,
ref: 'User'
},
timestamp: { type: Date, default: Date.now },
active: Boolean
});
ScheduleSchema.statics = {
load: function(cb) {
this.find({})
.populate({path:'participants'})
.exec(cb);
}
};
module.exports = mongoose.model('Schedule', ScheduleSchema);
When I create a new item in the Schedule model, this code sets it in motion (from a client-side controller):
$http.post('/api/schedules', { description: info.description, participants: attendees, meetingPlace: info.meetingPlace, office: info.office, start: info.start, end: info.end, timestamp: new Date(), active: true });
And because of this code:
'use strict';
var express = require('express');
var controller = require('./schedule.controller');
var router = express.Router();
router.get('/', controller.index);
router.get('/:id', controller.show);
router.post('/', controller.create);
router.put('/:id', controller.update);
router.patch('/:id', controller.update);
router.delete('/:id', controller.destroy);
module.exports = router;
I think the request is being routed to controller.create, which is the following:
'use strict';
var _ = require('lodash');
var Schedule = require('./schedule.model');
// Get list of schedules
exports.index = function(req, res) {
Schedule.load(function (err, schedules) { /*.find*/
if(err) { return handleError(res, err); }
return res.json(200, schedules);
});
};
// Get a single schedule
exports.show = function(req, res) {
Schedule.findById(req.params.id, function (err, schedule) {
if(err) { return handleError(res, err); }
if(!schedule) { return res.send(404); }
return res.json(schedule);
});
};
// Creates a new schedule in the DB.
exports.create = function(req, res) {
var promise = Schedule.create(req.body, function(err, schedule) {
if(err) { return handleError(res, err); }
return res.json(201, schedule);
});
};
// Updates an existing schedule in the DB.
exports.update = function(req, res){
var updatedMeeting = req.body;
var id = updatedMeeting._id;
delete updatedMeeting._id;
Schedule.update({_id : id}, updatedMeeting, { }, function (err, numberAffected, raw) {
if (err) return res.json(500, err);
updatedMeeting._id = id;
return res.json(201, updatedMeeting);
});
};
// Deletes a schedule from the DB.
exports.destroy = function(req, res) {
Schedule.findById(req.params.id, function (err, schedule) {
if(err) { return handleError(res, err); }
if(!schedule) { return res.send(404); }
schedule.remove(function(err) {
if(err) { return handleError(res, err); }
return res.send(204);
});
});
};
function handleError(res, err) {
return res.send(500, err);
}
After exports.create is run, and I don't know how, but something sends it over to here:
'use strict';
var Schedule = require('./schedule.model');
exports.register = function(socket) {
Schedule.schema.post('save', function (doc) {
onSave(socket, doc);
});
Schedule.schema.post('remove', function (doc) {
onRemove(socket, doc);
});
Schedule.schema.post('update', function (doc) {
onUpdate(socket, doc);
});
}
function onSave(socket, doc, cb) {
console.log('**********onSave**********');
Schedule
.findOne({ _id : doc._id })
.populate('participants')
.exec(function (err, event) {
if (err) return handleError(err);
socket.emit('schedule:save', event);
});
}
function onRemove(socket, doc, cb) {
socket.emit('schedule:remove', doc);
}
function onUpdate(socket, doc, cb) {
console.log('**********onUpdate**********');
socket.emit('schedule:update', doc);
}
and the line socket.emit('schedule:save', event); is called.
So that's all great, but when I update the Schedule model, I can't get socket to emit 'schedule:update' because it never gets to the "onUpdate" function in the code snippet just above this.
Starting from the client-side call:
$http.patch('/api/schedules/' + info._id, { _id: info._id, description: info.description, participants: attendees, meetingPlace: info.meetingPlace, office: info.office, start: info.start, end: info.end, timestamp: new Date(), active: true });
and the router sends that to exports.update, the model is updated, but socket doesn't emit anything, so all the clients connected see the old schedule information.
How and where can I relay to socket.io that the model has been updated? I think what I'm missing is how Schedule.schema.post('some action... gets called within the exports.register function, but I've been looking at this for a while and could use a hand - thanks.