Get Request using mongoose and Express - database

I'm trying to fetch the existing sample_mflix database from mongodb. At first I created a model for the movies collection.
This is my schema for movies
const mongoose = require("mongoose");
const movieSchema = new mongoose.Schema(
{
plot: {
type: String,
},
genres: [
{
type: String,
},
],
runtime: {
type: Number,
},
cast: [
{
type: String,
},
],
num_mflix_comments: {
type: Number,
},
title: {
type: String,
},
countries: [
{
type: String,
},
],
released: {
type: Date,
},
directors: [
{
type: String,
},
],
rated: {
type: String,
},
awards: {
wins: {
type: Number,
},
nominations: {
type: Number,
},
text: {
type: String,
},
},
lastupdated: {
type: String,
},
year: {
type: Number,
},
imdb: {
rating: {
type: Number,
},
votes: {
type: Number,
},
id: {
type: Number,
},
},
type: {
type: String,
},
poster: {
type: String,
},
writers: [
{
type: String,
},
],
tomatoes: {
viewer: {
rating: {
type: Number,
},
numReviews: {
type: Number,
},
meter: {
type: Number,
},
},
lastupdated: {
type: Date,
},
},
},
{ collection: "movies" }
);
const movies = mongoose.model("movies", movieSchema);
module.exports = movies;
this is my route to get all the movies from database
movieRoutes.js
const express = require("express");
const router = express.Router();
const movies = require("../models/movieModel");
router.get("/", async (req, res) => {
//res.send("Movie List");
try {
const allmovies = await movies.find({});
res.json(allmovies);
} catch (error) {
res.json(error);
}
});
module.exports = router;
But I'm unable to get any data in Postman. I'm pretty sure that the route is called but Postman loads forever and does not fetch.
How to fix this ?

Related

How do I update individual fields in nested objects that are in arrays in MongoDB using Mongoose?

This is my first post so please bear with me. I am building a LinkedIn clone and I am trying to keep track of the work experience, projects and courses of the users, and those will be kept in an array of objects inside of the User schema. Now let's say a user will try to add or update one of the elements in one of those arrays, I have the user ID and I am passing it to findOneAndUpdate() as the filter.
Here is my User schema:
const userSchema = new mongoose.Schema({
user_id: {
type: String,
required: [true, 'User ID required.'],
unique: true,
immutable: true,
},
name: {
type: String,
required: [true, 'Name required.'],
},
email: {
type: String,
required: [true, 'Email required.'],
unique: true,
lowercase: true,
immutable: true,
},
title: {
type: String,
},
location: {
type: String,
},
phone_number: {
type: String,
},
contact_email: {
type: String,
},
photo: {
type: String,
},
website: {
type: String,
},
backdrop: {
type: String,
},
summary: {
type: String,
},
work: {
type: String,
},
connections: {
type: Number,
},
projects: [
{
title: {
type: String,
},
description: {
type: String,
},
start_date: {
type: Date,
},
end_date: {
type: Date,
},
technologies: {
type: String,
},
picture: {
type: String,
},
},
],
skills: [{
skill: {
name: {
type: String,
},
level: {
type: String,
},
},
}],
experience: [
{
company: {
type: String,
},
logo: {
type: String,
},
title: {
type: String,
},
location: {
type: String,
},
start_date: {
type: Date,
},
end_date: {
type: Date,
},
description: {
type: String,
},
},
],
education: [
{
school: {
type: String,
},
logo: {
type: String,
},
degree: {
type: String,
},
location: {
type: String,
},
start_date: {
type: Date,
},
end_date: {
type: Date,
},
description: {
type: String,
},
},
],
languages: [
{
name: {
type: String,
},
level: {
type: String,
},
},
],
awards: [
{
title: {
type: String,
},
date: {
type: Date,
},
awarder: {
type: String,
},
summary: {
type: String,
},
},
],
courses: [
{
title: {
type: String,
},
number: {
type: String,
},
school: {
type: String,
},
start_date: {
type: Date,
},
end_date: {
type: Date,
},
description: {
type: String,
},
},
],
});
And in my UserController.ts file, I tried using this:
const updateUser = async (req: Request, res: Response) => {
try {
const filter = { user_id: req.body.user_id };
const update = req.body;
const updatedUser = await User.findOneAndUpdate(filter, update, {
new: true,
upsert: true,
});
res.status(201).json({
status: 'success',
data: {
user: updatedUser,
},
});
} catch (err) {
res.status(400).json({
status: `ERROR: ${err}`,
message: 'error updating user',
});
}
};
And in my request using the format of the schema but that didn't work out as expected. I know mongoose will automatically give it an _id field to each of the individual objects in the array, but again, I have had no luck updating them. I tried sending a PATCH request with this as the body to add a skill like so:
{
"user_id": "xxxxxxxxxxxxxxxx",
"title": "Mr.",
"skills" : {
"name": "Flute",
"level": "Novice"
}
}
And this was the response I got. It created a skill but didnt add the data in the skill object:
{
"status": "success",
"data": {
"user": {
"_id": "63d3715f2ef9698667230a53",
"user_id": "xxxxxxxxxxxxxxxx",
"name": "Jonathan Abitbol",
"email": "yoniabitbol1#gmail.com",
"projects": [],
"skills": [
{
"_id": "63d4068d2df30c9e943e4608"
}
],
"experience": [],
"education": [],
"languages": [],
"awards": [],
"courses": [],
"__v": 0,
"title": "Mr."
}
}
}
Any help on how to add/edit the nested objects would be appreciated.

how can i return an array of strings in graphQL - proper setup?

Hi I am trying to figure out why I am not returning an array of strings. I have read the docs and i must say, im stuck im a bit new to this sorry for the dumb question but can someone please help me figure this out?
I cant seem to get "flickr_images": to return an array of strings. I dont know how to proceed from there. "flicker_images" constantly return null.
I setup my graphql schema like this
`
const LaunchType = new GraphQLObjectType({
name: 'Launch',
fields: () => ({
flight_number: { type: GraphQLInt },
mission_name: { type: GraphQLString },
launch_year: { type: GraphQLString },
launch_date_local: { type: GraphQLString },
launch_success: { type: GraphQLBoolean },
details: { type: GraphQLString },
rocket: { type: RocketType },
launch_site: { type: LaunchSite },
links: { type: UrlType },
}),
});
const RocketType = new GraphQLObjectType({
name: 'Rocket',
fields: () => ({
rocket_id: { type: GraphQLString },
rocket_name: { type: GraphQLString },
rocket_type: { type: GraphQLString },
}),
});
const UrlType = new GraphQLObjectType({
name: 'Url',
fields: () => ({
mission_patch_small: { type: GraphQLString },
flickr_images: { type: new GraphQLList(GraphQLString) },
}),
});
rocket: {
type: RocketType,
args: {
id: { type: GraphQLInt },
},
resolve(parent, args) {
return axios
.get(`https://api.spacexdata.com/v3/rockets/${args.id}`)
.then((res) => res.data);
},
},
links: {
type: UrlType,
args: {
flight_number: { type: GraphQLInt },
},
resolve(parent, args) {
return axios
.get(`https://api.spacexdata.com/v3/launches/${args.flight_number}`)
.then((res) => res.data);
},
},
`
UPDATED
I'm guessing that axios.get(api.spacexdata.com/v3/rockets/${args.id}) isn't returning an array of flickr images as part of its payload. You're going to need a separate resolver under your rocket to resolve that field.

Mongoose updating subdocument array

I want to update rooms subdocument which is in Property document, but I get this error:
MongoServerError: Updating the path 'rooms.$.updatedAt' would create a
conflict at 'rooms.$'
Error which i got in postman:
{
"ok": 0,
"code": 40,
"codeName": "ConflictingUpdateOperators",
"$clusterTime": {
"clusterTime": {
"$timestamp": "7137698220989218823"
},
"signature": {
"hash": "34spx6E0zZFa5bVYFSL2JyjFszQ=",
"keyId": {
"low": 2,
"high": 1646669662,
"unsigned": false
}
}
},
"operationTime": {
"$timestamp": "7137698220989218823"
}
}
My property model:
import { IReview, ReviewSchema } from './reviews.model'
import { IRoom, RoomSchema } from './room.model'
type TCheapestRoom = {
roomType: string
bedType: string
lastPrice: number
actualPrice: number
}
export interface IProperty {
propertyType: string
name: string
description: string
city: string
photos: [string]
cheapestRoom: TCheapestRoom
adress: string
distance: number
cancellationPolicy: string
meals: string
funThingsToDo: [string]
accessibility: [string]
rooms: IRoom[]
reviews: IReview[]
}
interface IPropertyDocument extends IProperty, Document {
createdAt: Date
updatedAt: Date
// rooms: Types.Array<IRoom>
}
const PropertySchema = new Schema<IPropertyDocument>(
{
propertyType: { type: String, required: true },
name: { type: String, required: true },
description: { type: String, required: true },
city: { type: String, required: true },
photos: { type: [String] },
cheapestRoom: {
roomType: { type: String },
bedType: { type: String },
lastPrice: { type: Number },
actualPrice: { type: Number },
},
adress: { type: String, required: true },
distance: { type: Number, required: true },
cancellationPolicy: { type: String, required: true },
meals: { type: String, required: true },
funThingsToDo: { type: [String] },
accessibility: { type: [String] },
rooms: [RoomSchema],
reviews: [ReviewSchema],
},
{
timestamps: true,
}
)
const PropertyModel = model<IPropertyDocument>('Property', PropertySchema)
export default PropertyModel
Subdocument room model:
export interface IRoom {
roomType: string
bedTypes: [string]
roomFacilities: [string]
sleeps: number
lastPrice: number
actualPrice: number
cancellation: string
payment: string
breakfast: string
unavailableDates: [Date]
}
export interface IRoomDocument extends IRoom, Document {
createdAt: Date
updatedAt: Date
}
export const RoomSchema = new Schema<IRoomDocument>(
{
roomType: { type: String, required: true },
bedTypes: { type: [String], required: true },
roomFacilities: { type: [String], required: true },
sleeps: { type: Number, required: true, default: 2 },
lastPrice: { type: Number, required: true },
actualPrice: { type: Number, required: true },
cancellation: { type: String, required: true },
payment: { type: String, required: true },
breakfast: { type: String, required: true },
unavailableDates: { type: [Date] },
},
{
timestamps: true,
}
)
const RoomModel = model<IRoomDocument>('Room', RoomSchema)
export default RoomModel
room controller:
import PropertyModel from '../models/property.model'
import RoomModel from '../models/room.model'
const updateRoom = async (req: Request, res: Response) => {
try {
const updatedProperty = await PropertyModel.findOneAndUpdate(
{ _id: req.params.propertyId, 'rooms._id': req.params.roomId },
{
$set: { 'rooms.$': req.body },
},
{
new: true,
}
)
res.status(201).json(updatedProperty)
} catch (error) {
console.log(error)
res.status(400).json(error)
}
}
export { addNewRoom, deleteRoom, updateRoom }
I want to be able updating my subdocuments, in this case rooms using property id and room id.
How can i update this subdocument ?

Sequelize hasOne and belongsTo relationship problem

i am using PostgreSQL with Sequelize ORM to create my db.
I have this models:
models.js
const Users = db.define("users", {
name: {
type: DataTypes.STRING,
},
lastname: {
type: DataTypes.STRING,
},
sector: {
type: DataTypes.STRING,
},
email: { type: DataTypes.STRING, unique: true, allowNull: false },
password: { type: DataTypes.STRING, allowNull: false },
points: { type: DataTypes.INTEGER, defaultValue: 0 },
suscripcion: { type: DataTypes.BOOLEAN, defaultValue: false },
preference_id: { type: DataTypes.STRING },
});
const Pronostico = db.define("pronosticos", {
matchId: {
type: DataTypes.STRING,
unique: true,
},
winner: {
type: DataTypes.STRING,
},
goalHome: {
type: DataTypes.INTEGER,
},
goalAway: {
type: DataTypes.INTEGER,
},
});
//REFRESH TOKEN
const RefreshToken = db.define("refreshTokens", {
token: {
type: DataTypes.STRING,
},
expiryDate: {
type: DataTypes.DATE,
},
userId: {
type: DataTypes.STRING,
},
});
RefreshToken.createToken = async function (user) {
let expiredAt = new Date();
expiredAt.setSeconds(expiredAt.getSeconds() + config.jwtRefreshExpiration);
let _token = uuidv4();
let refreshToken = await this.create({
token: _token,
userId: user.id,
expiryDate: expiredAt.getTime(),
});
return refreshToken.token;
};
RefreshToken.verifyExpiration = (token) => {
return token.expiryDate.getTime() < new Date().getTime();
};
This are the Relationships:
Users.hasMany(Pronostico, { as: "pronosticos" });
Pronostico.belongsTo(Users, { foreignKey: "userId", as: "user" });
RefreshToken.belongsTo(User, {
foreignKey: 'userId', targetKey: 'id'
});
User.hasOne(RefreshToken, {
foreignKey: 'userId', targetKey: 'id'
});
Somewhere on my server, I have this controller which creates a refreshToken:
let refreshToken = await RefreshToken.createToken(user);
The problem is that I get an error that says "column userId doesnt exist in refreshTokens relationship.
Maybe I have some issues with the relationships but I think they are OK.
Any suggestion?

Mongoose: 'Cast to embedded failed for value at path. Cannot use 'in' operator to search for '_id'

I'm having some trouble trying to save an array inside an array of objects.
I'm getting the following response from the server:
{ [CastError: Cast to embedded failed for value "\'maxbeds: 4\'" at path "saved_searches"]
message: 'Cast to embedded failed for value "\\\'maxbeds: 4\\\'" at path "saved_searches"',
name: 'CastError',
kind: 'embedded',
value: '\'maxbeds: 4\'',
path: 'saved_searches',
reason: [TypeError: Cannot use 'in' operator to search for '_id' in maxbeds: 4] }
Here's my Schema:
var mongoose = require('mongoose'),
rfr = require('rfr'),
passwordHelper = rfr('server/helpers/password.js'),
Schema = mongoose.Schema,
_ = require('lodash');
/*
*
* Creating UserSchema for MongoDB
*
*/
var UserSchema = new Schema({
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true,
select: false
},
name: {
type: String,
required: true
},
passwordSalt: {
type: String,
required: true,
select: false
},
saved_houses: [{
mlsId: {
type: String
},
addressFull: {
type: String
},
bedrooms: {
type: Number
},
listPrice: {
type: Number
},
bathrooms: {
type: Number
},
sqft: {
type: Number
},
createdAt: {
type: Date,
default: Date.now
}
}],
saved_searches: [{
search_name: {
type: String
},
filters: {
type: [Schema.Types.Mixed]
},
createdAt: {
type: Date,
default: Date.now
}
}],
active: {
type: Boolean,
default: true
},
createdAt: {
type: Date,
default: Date.now
}
});
// compile User model
module.exports = mongoose.model('User', UserSchema);
The problem, I believe is the filters array that live inside an object inside the saved_searches array
Now, in my router I do the following:
var express = require('express'),
savedDataRouter = express.Router(),
mongoose = require('mongoose'),
rfr = require('rfr'),
s = rfr('server/routes/config/jwt_config.js'),
User = rfr('server/models/User.js'),
jwt = require('jsonwebtoken');
savedDataRouter.post('/searches', function (req, res) {
if (mongoose.Types.ObjectId.isValid(req.body.userId)) {
User.findByIdAndUpdate({
_id: req.body.userId
}, {
$push: {
saved_searches: {
search_name: req.body.search_name,
$each: req.body.filters
}
},
}, {
new: true
},
function (err, doc) {
if (err || !doc) {
console.log(err);
res.json({
status: 400,
message: "Unable to save search." + err
});
} else {
return res.json(doc);
}
});
} else {
return res.status(404).json({
message: "Unable to find user"
});
}
});
If I log the request body coming from the client I get the following:
//console.log(req.body)
{ search_name: 'Sarasota',
filters: [ 'minbaths: 1', 'maxbaths: 3', 'minbeds: 2', 'maxbeds: 4' ],
userId: '583359409a1e0167d1a3a2b3' }
I've tried all the things I've seen in Stack Overflow and other online resources with no luck. What am I doing wrong?
Edit
Added module dependencies to my UserSchema and SavedDataRouter
try this
User.findByIdAndUpdate({
_id: req.body.userId
}, {
$push: {
saved_searches: {
search_name: req.body.search_name,
filters: req.body.filters
}
},
}, {
new: true
},
function (err, doc) {
if (err || !doc) {
console.log(err);
res.json({
status: 400,
message: "Unable to save search." + err
});
} else {
return res.json(doc);
}
});

Resources