I have an issue on my application (mongodb/nodejs), my aim is to save a collection :
const Job = require("../models/Job");
exports.saveJob = (req, res, next) => {
const newJob = new Job(req.body);
newJob.gender = 'Male';
newJob.save((err, myjob) => {
myjob.code = '1234';
myjob.save((err, mysavedjob) => {
console.log(mysavedjob);
/** OUTPUT **
* { __v: 0,
updatedAt: 2018-07-31T08:31:47.664Z,
createdAt: 2018-07-31T08:31:47.664Z,
gender:'Male',
code:'1234',
...
}
*/
})
})
}
As you can see, the code output the saved document, but when I check the database , I don't have the code:'1234' I have just
{ __v: 0,
updatedAt: 2018-07-31T08:31:47.664Z,
createdAt: 2018-07-31T08:31:47.664Z,
gender:'Male',
...
}
==== UPDATE (adding the JobModel) ====
const mongoose = require("mongoose");
const JobSchema = new mongoose.Schema(
{
userId: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
code: String,
gender: String,
},
{ timestamps: true }
);
module.exports = mongoose.model("Job", JobSchema, "jobs");
Someone could tell me why please ?
thank you.
I am not sure this is the correct way to alter a job after saving it but try this
const Job = require("../models/Job");
exports.saveJob = (req, res, next) => {
const newJob = new Job(req.body);
newJob.gender = 'Male';
newJob.save((err, myjob) => {
myjob.code = '1234';
Job.findOneAndUpdate({_id: myjob._id}, myjob, (err, mysavedjob) => {
console.log(mysavedjob);
});
})
}
Related
I have a problem with mongoose. I use MEAN stack.
I have an House Schema with some fields. When I update the house (with save method) mongoose update all fields but set an array in nested object empty. Why?
HOUSE SCHEMA
const mongoose = require('mongoose');
const posSchema = require('./pos');
const reviewSchema = require('./reviews');
const roomSchema = require('./rooms');
const contactSchema = require('./contacts');
const nearSchema = require('./nears');
const houseSchema = new mongoose.Schema({
title: { type: String, required: true },
description: { type: String, required: true },
shared: {
description: { type: String, required: true },
photos: { type: [String], required: true }
},
// OTHER FIELDS
}, { timestamps: true });
mongoose.model('House', houseSchema);
UPDATE FUNCTION
House.findById(body.house._id, "-__v", async (err, house) => {
if (err) { return res.status(400).json(err); }
else if (!house) { return res.status(400); }
house.title = body.house.title;
house.totalSize = parseInt(body.house.totalSize.toString());
house.bathrooms = parseInt(body.house.bathrooms.toString());
house.totalBeds = parseInt(body.house.totalBeds.toString());
house.description = body.house.description;
house.totalFreeBeds = parseInt(body.house.totalFreeBeds.toString());
house.minPrice = parseFloat(body.house.minPrice.toString()).toFixed(2);
house.type = body.house.type;
house.level = body.house.level;
house.top_floor = body.house.top_floor;
house.rooms = body.house.rooms;
house.checkboxes = body.house.checkboxes;
house.contacts = body.house.contacts;
house.pos = body.house.pos;
house.save(err => {
if (err) { console.log(err); return res.status(400).json(err); }
return res.status(200).json({ status: 200, remove: remove });
});
});
Before updating house.shared.photos is ["foo", "bar"]
After is [].
Why?
You are not setting the house.shared anywhere.
Try adding house.shared = body.house.shared before save call.
I am trying to unit test my code, I am using Node.js, Express, MongoDB, Mongoose and trying to test it with Jest.
I am having issues with the in-memory mongo db with Jest. I have read the documentation (https://jestjs.io/docs/en/mongodb).
When trying to test a query for one of my Mongoose models, I believe that my query is not pointing at the correct place, I would like it to run its query against the in-memory collection.
My current test setup:
const { MongoClient } = require("mongodb");
const Preferences = require("./preferences");
const mongoose = require("mongoose");
const ObjectId = mongoose.Types.ObjectId;
describe("Preference helper function", () => {
let connection;
let db;
let userPreferences;
const testUser = new Preferences({
userId: ObjectId("5eef15429e93464b3ccae235"),
wordPreferences: [
{ wordId: 1, active: true},
{ wordId: 2, active: true},
{ wordId: 3, active: true},
{ wordId: 4, active: true},
{ wordId: 5, active: true}
],
});
beforeAll(async () => {
connection = await MongoClient.connect(global.__MONGO_URI__, {
useNewUrlParser: true,
});
db = await connection.db(global.__MONGO_DB_NAME__);
});
afterAll(async () => {
await connection.close();
await db.close();
});
beforeEach(async () => {
userPreferences = await db.collection("userPreferences");
});
afterEach(async () => {
await userPreferences.deleteMany();
});
it("get active words function gives correct result", async () => {
await userPreferences.insertOne(testUser);
const expectedResult = [1, 2, 3, 4, 5];
let queryResult = await Preferences.getActiveWordIds(testUser.userId);
expect(queryResult).toEqual(expectedResult);
});
});
Running this code gives the following error:
Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Timeout - Async callback was not invoked within the 5000 ms timeout specified by jest.setTimeout.Error
Changing the timeout for this does not resolve the problem as it appears the query does not resolve. Here is the the Moongoose model for the Preference model used in the test above:
const mongoose = require("mongoose");
const PreferenceMappingSchema = require("../preference-mapping");
var PreferenceSchema = new mongoose.Schema({
userId: {
type: mongoose.Types.ObjectId,
required: true,
},
wordPreferences: {
type: [PreferenceMappingSchema],
required: true,
},
});
// Choose the correct db and set the model
const db = mongoose.connection.useDb("users");
const Preferences = (module.exports = db.model("Preference", PreferenceSchema));
module.exports.getActiveWordIds = async function(userId) {
try {
const user = await Preferences.aggregate([
// Get the current users doc
{ $match: { userId: userId} },
{
$project: {
wordPreferences: {
// Get only active words
$filter: {
input: "$wordPreferences",
as: "pref",
cond: {
$eq: ["$$pref.active", true],
},
},
},
},
}
]).exec();
// Map to list of valid numbers
return user[0]['wordPreferences'].map(x => x.wordId);
} catch (error) {
console.warn(error);
throw error;
}
};
Thanks in advance for any help!
I have a pipeline and its result I want to return it by an express method that is get or not i know if it is more advisable to send it by a socket
this is my file pipeline.js:
function getModel(model) {
model.aggregate([{
$group: {
_id: null,
"price": {
$sum: "$price",
}
}
}]).exec((e, d) => {
return JSON.stringify(d)
})
}
module.exports = getModel;
in the model.js file I'm going to call my pipeline.js file and therefore the function
model.js:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const getModel = require('./pipeline');
const mySchema = new Schema({
user: {
type: Schema.ObjectId,
ref: 'User'
},
namepet: String,
type_of_service: String,
characteristic_of_pet: String,
price: Number
});
const model = mongoose.model('Cites', mySchema);
here is the function-> getModel(model);
module.exports = model;
and it works for me as I want the problem is that the result I have to send it by a method get and I have no idea how to do it
How can I send the result indicating the red arrow of the image by a get method?
var express = require('express');
var app = express();
function getModel(model) {
model.aggregate([{
$group: {
_id: null,
"price": {
$sum: "$price",
}
}
}]).exec((e, d) => {
return JSON.stringify(d)
})
}
app.get('/', function(req, res) {
console.log('marhaba');
res.send(getModel( ** Model ** ))) //== > here call the getModel function
});
app.listen(3000, function() {
console.log("Working on port 3000");
});
I am very new to mongoose.
I am currently building a backend using Node.js, express.js, GraphQL, and mongoose.
I have a Drink schema and DrinkType Schema. I defined DrinkType schema as "alcohol", "juice", "tea". And I have added many drinks and each drink has DrinkType reference. Then, I would like to reference all the drinks from DrinkType.
This is the schema for drinkType
const drinkTypeSchema = new Schema({
name: {
type: String,
required: true,
},
createdDrinks: [
{
type: Schema.Types.ObjectId,
ref: 'Drink',
},
],
Here is the schema for drink
const drinkSchema = new Schema({
name: {
type: String,
required: true,
},
drinkType: {
type: Schema.Types.ObjectId,
ref: 'DrinkType',
},
})
This is the drink resolver. Whenever a new drink is created, I am pushing it to drinkType.
try {
const result = await drink.save()
createdDrink = transformDrink(result)
const drinkType = await DrinkType.findById(args.addDrinkInput.drinkTypeId)
if (!drinkType) {
throw new Error('DrinkType not found.')
}
drinkType.createdDrinks.push(drink)
await drinkType.save()
const drinkLoader = new DataLoader(drinkIds => {
return drinks(drinkIds)
})
const drinks = async drinkIds => {
try {
const drinks = await Drink.find({ _id: { $in: drinkIds } })
return drinks.map(drink => {
return transformDrink(drink)
})
} catch (err) {
throw err
}
}
const transformDrink = drink => {
return {
...drink._doc,
_id: drink.id,
drinkType: drinkType.bind(this, drink.drinkType),
}
}
const drinkType = async drinkTypeId => {
try {
const drinkType = await drinkTypeLoader.load(drinkTypeId.toString())
return {
...drinkType._doc,
_id: drinkType.id,
createdDrinks: () => drinkLoader.loadMany(drinkType._doc.createdDrinks),
}
I want this createdDrinks part to return the array of drink objects, but it is only returning the array of _ids.
I have been reading the mongoose documentation and it seems that using ObjectId is the correct way. Would you mind helping me out?
Thank you in advance.
I have several collections that have the same documents type, except for the language.
Let's say imagesES, imagesEN, imagesFR, and so on....
I just thought about definig just one schema, but also one model that get the proper collection with a parameter:
var mongoose = require('mongoose')
var Schema = mongoose.Schema
let authorSchema = require('./Authors').authorSchema
const imageSchema = new Schema({
authors: [authorSchema],
status: Number, // published (1), unpublished (0)
created: { type: Date, default: Date.now },
lastUpdated: { type: Date, default: Date.now },
license: {
type: String,
enum: ['Creative Commons BY-NC-SA'], //just one license right now
default: 'Creative Commons BY-NC-SA'
},
downloads: {
type: Number,
default: 0
},
tags: [String]
})
module.exports = locale => {
return mongoose.model('Image', imageSchema, `image${locale}`)
}
However in the controller I should require the model inside the controller (when I know the locale):
getImageById: (req, res) => {
const id = req.swagger.params.id.value
const locale = req.swagger.params.locale.value
const Images = require('../models/Images')(locale)
Images.findOne({_id: id}).lean().exec( (err, image) => {
I'm not sure if this is the proper way as each request I get I have to require the model module (syncronously) or should I require all the different models previous to the use in the function.
const locales = ['es', 'en', 'fr']
const Images = []
locales.map(locale=>Images[locale] = require('../models/Images')(locale))
getImageById: (req, res) => {
const id = req.swagger.params.id.value
const locale = req.swagger.params.locale.value
Images[locale].findOne({_id: id}).lean().exec( (err, image) => {
Finally this is how I resolved it. Where it says Pictograms, could be Images as in the question
const setPictogramModel = require('../models/Pictograms')
const languages = [
'ar',
'bg',
'en',
'es',
'pl',
'ro',
'ru',
'zh'
]
const Pictograms = languages.reduce((dict, language)=> {
dict[language]= setPictogramModel(language)
return dict
}, {})
module.exports = {
getPictogramById: (req, res) => {
const id = req.swagger.params.idPictogram.value
const locale = req.swagger.params.locale.value
// Use lean to get a plain JS object to modify it, instead of a full model instance
Pictograms[locale].findOne({id_image: id}).exec( (err, pictogram) => {
if(err) {
return res.status(500).json({
message: 'Error getting pictograms. See error field for detail',
error: err
})
}
if(!pictogram) {
return res.status(404).json( {
message: `Error getting pictogram with id ${id}`,
err
})
}
return res.json(pictogram)
})
},