Currently, I'm writing an app on Node.js 5.2.0 on a Linux box with Redis and Caminte. When trying to add different prototype methods to a database object, the context of what this refers to constantly shifts within our reference. After calling push in modelRules.js, this shifts types. I was looking for some assistance with:
How to consistently reference the instantiation of a specific module (function that accepts a schema object) outside of the module itself. I want to tack on prototype functions such as addModelBelongsTo to a User object, and sadly my function simply seems to break when referencing the internal modifiable data members within the class.
The proper organization of the prototype accessors. Is there a specific style that should be used when referencing the insides of the instantiations of these classes?
Why the instantiation of the class User persists data across multiple instantiations of the class? For self[restructuredModelName] (type of array), whenever I call this method on one instantiation, another instantiation of the other object already contains the data of the first instantiation. This should not be happening.
User.js
module.exports = function (schema) {
const IBANVerificationStatusSymbol = Symbol('IBANVerificationStatus');
const relationalMapper = require('./../relationalMapper');
const userObj = {
id: { type: schema.Number },
firstName: { type: schema.String },
lastName: { type: schema.String },
IBAN: { type: schema.String, unique: true },
IBANVerified: { type: schema.Boolean, default: false },
IBANVerificationCode: { type: schema.String },
BIC: { type: schema.String },
email: { type: schema.String, index: true, unique: true },
password: { type: schema.String },
status: { type: schema.Number, default: 0 },
profilePicture: { type: schema.String },
phone: { type: schema.String, index: true, unique: true },
accessToken: { type: schema.String },
prefix: { type: schema.String, default: '+31' },
updated: { type: schema.Date, default: Date.now() },
created: { type: schema.Date, default: Date.now() },
lastAccessedFeed: { type: schema.Date },
street: { type: schema.String },
streetNumber: { type: schema.String },
postalCode: { type: schema.String },
city: { type: schema.String },
country: { type: schema.String },
FCR: { type: schema.Number, default: 0 },
};
// There's GOTTA be a way to typecheck at compilation
const associationMap = {
Activity: { belongsTo: 'Activity', hasMany: 'activities' },
Client: { belongsTo: null, hasMany: 'clients' },
Group: { belongsTo: 'Group', hasMany: 'groups' },
Mandate: { belongsTo: null, hasMany: 'mandates' },
Transaction: { belongsTo: null, hasMany: 'transactions' },
Update: { belongsTo: null, hasMany: 'updates' },
Reaction: { belongsTo: null, hasMany: 'reactions' },
};
relationalMapper.createRelations(associationMap, userObj, schema);
const User = schema.define('user', userObj, {
});
const setId = function (self, models) {
// self.addClients(1);
};
User.hooks = {
afterInitialize: [setId],
};
User.prototype.obj = userObj;
User.associationMap = associationMap;
User.prototype.associationMap = associationMap;
return User;
};
modelRules.js:
function addModelBelongsTo(modelName, models, modelObjKey, modelRelated) {
const restructuredModelName = `memberOf${modelName}`;
const restructuredModelNameCamel = `addMemberOf${modelName}`;
const currentModels = models;
currentModels[modelObjKey].prototype[restructuredModelNameCamel] = function(modelId) {
const self = this;
return new Promise((resolve, reject) => {
if (self[restructuredModelName].indexOf(modelId) <= -1) {
modelRelated.exists(modelId, function(err, exists) {
if (err || !exists) { reject(new Error(err || 'Doesnt exist')); }
console.log(`This:${self}\nrestructuredModelName:${JSON.stringify(self[restructuredModelName])}`);
self[restructuredModelName].push(modelId);
console.log(`This:${self}\nrestructuredModelName:${restructuredModelName}`);
self.save((saveErr) => {
saveErr ? reject(new Error(saveErr)) : resolve(self);
});
});
} else {
reject(new Error(''));
}
});
};
}
Related
I'm using NestJS in the vanillaJS way (because I can't write typescript) and I have a many-to-many relation from user to bubble.
I want to write a updateUser-Route in which I also want to be able to update the bubble-affiliation.
But when I do so like this:
user.controller.js:
#Patch(':id')
#Bind(Param('id'), Body())
async updateUser(id, body) {
if (Object.keys(body).length !== 0) {
return await this.userService.updateUser(id, body);
}
throw new BadRequestException('Missing Body');
}
user.service.js:
async updateUser(id, user) {
return await this.userRepository.update(id, user);
}
I get this error:
Cannot query across many-to-many for property bubble
This is my user.entity.js:
var EntitySchema = require('typeorm').EntitySchema;
var User = require('./user.model').User;
var Bubble = require('../bubble/bubble.model').Bubble;
module.exports = new EntitySchema({
name: 'User',
target: User,
columns: {
id: {
primary: true,
type: 'int',
},
handle: {
type: 'varchar',
},
lastCheck: {
type: 'datetime',
default: () => 'NOW()',
},
rating: {
type: 'int',
},
},
relations: {
bubble: {
type: 'many-to-many',
target: 'Bubble',
joinTable: true,
cascade: true,
},
},
});
in postman I try to call it like this:
{
"rating": 10,
"bubble": [{
"id": "1234"
}]
}
if I leave bubble out it works and rating gets updated. with bubble I get the error described above
Here is my schema by using mongoose npm package.
var StatusSchema = new mongoose.Schema({
empName: {
projectName: { type: String },
clientName: { type: String },
statusLastWeek: { type: String },
statusThisweek: { type: String },
planNextWeek: { type: String }
}
});
Here is my nodejs code to update the data
var Status = mongoose.model('Status', StatusSchema);
module.exports = Status;
Description: Want save data in MongoDB, data schema is like above mentioned,
save saving data is sored loke as bellow.
Inside Mongo DB :
{ "_id" : ObjectId("5d92f4aba4695e2dd90ab438"), "__v" : 0 }
{ "_id" : ObjectId("5d92f4b4a4695e2dd90ab439"), "__v" : 0 }
Expected collection in MongoDB :
Dave Smith {
projectName: BLE Mesh,
clientName: Tera,
statusLastWeek: BLE Scan,
statusThisweek: BLE List View,
planNextWeek: Mqtt config
}
Here you can see my NodeJS code :
router.post ('/update', (req,res,next)=>{
userStatus = new wkStatus(req.body)
userStatus.save()
.then(status => {
res.redirect('/success');
console.log ("Status saved in DB")
})
.catch(err => console.log(err))
// return next;
});
//You can use ODM like mongoose and define a schema with mongoose.Schema. You can just
// see mongoose module document from npm. Use .save() for save an object in DB.
// Example :
// schema as admin
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const Schema = mongoose.Schema;
const bcrypt = require('bcrypt-nodejs');
const sha256 = require('sha256')
const adminSchema = new Schema({
fullName: { type: String, required: true },
userName: { type: String },
noc: { type: String, required: true },
mobileNumber: { type: String, required: true },
email: { type: String },
chacommAddress: {
contactPerson: { type: String },
country: { type: String },
address: { type: String },
city: { type: String },
pinCode: { type: String },
state: { type: String },
stateCode: { type: String },
},
address: {
country: { type: String },
city: { type: String },
pinCode: { type: String },
state: { type: String },
stateCode: { type: String },
address: { type: String },
CIN: { type: String },
GSTIN: { type: String }
},
password: { type: String, required: true },
userType: { type: Number, required: true },
createdAt: { type: Date, required: true },
uploadFile: { type: String, required: true },
bankdetails: {
bankName: { type: String },
accountNo: { type: String },
ifscCode: { type: String },
accountType: { type: String },
accountName: { type: String },
cancelledChequeCopy: { type: String }
},
isActive: { type: Boolean },
invoiceString:{type:String},
invoiceValue:{type:Number},
accountantName :{type:String} ,
accountantDesignation : {type:String},
referredBy:{type:String}
});
adminSchema.methods.comparePassword = function (password) {
let password_hash = sha256(password);
return bcrypt.compareSync(password_hash, this.password);
}
adminSchema.pre('save', function (next) {
if (!this.isModified('password'))
return next();
let password_hash = sha256(this.password);
bcrypt.hash(password_hash, null, null, (err, hash) => {
if (err)
return next(err);
this.password = hash;
next();
});
});
//export schema
// module.exports = mongoose.model('Admin', adminSchema)
// for save:
const admin = require('admin')
var obj= new admin({
// values as per model defined
})
obj.save()
const wkStatus = new wkStatus({
_id: new mongoose.Types.ObjectId(),
projectName: req.body.projectName,
clientName: req.body.clientName,
statusThisweek: req.statusThisweek,
statusLastWeek: req.statusLastWeek,
planNextWeek: req.planNextWeek
})
Status
.save()
.then(result => {
res.status(201).json({
message: "Data Created Successfully",
})
console.log(result) // show the response
})
.catch(err => {
res.status(500).json({error:err})
})
Try this way hope it will work. If need more you can message me
The schema what you are trying to create itself is wrong.
empName: {
projectName: { type: String },
clientName: { type: String },
statusLastWeek: { type: String },
statusThisweek: { type: String },
planNextWeek: { type: String }
}
The above schema can create objects like below: "empName" cannot be dynamic.
empName: {
projectName: BLE Mesh,
clientName: Tera,
statusLastWeek: BLE Scan,
statusThisweek: BLE List View,
planNextWeek: Mqtt config
}
If you want to store like what you have shown, where empName dynamically then you should make empName as Map
See https://mongoosejs.com/docs/schematypes.html#maps
Disclaimer: I am very new to
Node/Express/Sequelize
Questions:
1. Do I need to import visitors.js to visitorsInfo.js so that I can create an association between the 2?
2. If not, how do I set up the visitorsInfo_id as a Foreign Key from visitors.js column visitors_id?
Snippet:
...model/visitors.js
'use strict'
module.exports = ( sequelize , type ) => {
return sequelize.define( 'visitors' , {
visitor_id: {
type: type.INTEGER,
primaryKey: true,
autoIncrement: true
},
web_status: {
type: type.BOOLEAN
},
digital_status: {
type: type.BOOLEAN
},
hosting_status: {
type: type.BOOLEAN
},
training_status: {
type: type.BOOLEAN
},
})
}
.../model/visitors_info.js
'use strict'
module.exports = ( sequelize , type) => {
return sequelize.define( 'user_info' , {
visitorsInfo_id: {
type: type.INTEGER,
/*
How to set up foreign key...?
*/
},
firstname: {
type: type.STRING
},
lastname: {
type: type.STRING
},
company: {
type: type.STRING
},
contact_info: {
type: type.INTEGER
}
})
}
No need import visitors.js to visitorsInfo.js
Base on the document from Sequelize, In file visitorsInfo.js
'use strict'
module.exports = ( sequelize , type) => {
var user_info = sequelize.define( 'user_info' , {
visitorsInfo_id: {
type: type.INTEGER,
},
firstname: {
type: type.STRING
},
lastname: {
type: type.STRING
},
company: {
type: type.STRING
},
contact_info: {
type: type.INTEGER
}
});
user_info.associate = function (models) {
// associations can be defined here
user_info.belongsTo(models.visitors, {
as: 'visitors',
foreignKey: 'visitorsInfo_id',
targetKey: 'visitor_id'
});
}
return user_info
}
I want to use mutation in Relay to change an array (not connection). The array is typed GraphQLList in the GraphQL side. The graphql side worked perfectly, but relay side needs dataID for each item in an array. And when I am inserting new item or modifying existing item in the array, there are no dataID provided? What is the right way to do this? By the way, I am using redux to maintain the list, and submit changes via relay at the end.
The schema:
let widgetType = new GraphQLInputObjectType({
name: 'Widget',
fields: () => ({
label: {
type: GraphQLString
},
type: {
type: GraphQLString
},
list: {
type: new GraphQLList(GraphQLString)
},
description: {
type: GraphQLString
},
required: {
type: GraphQLBoolean
}
})
});
let modifyFormMutation = mutationWithClientMutationId({
name: 'ModifyForm',
inputFields: {
id: {
type: new GraphQLNonNull(GraphQLString)
},
name: {
type: new GraphQLNonNull(GraphQLString)
},
userId: {
type: new GraphQLNonNull(GraphQLString)
},
widgets: {
type: new GraphQLList(widgetType)
}
},
outputFields: {
formEdge: {
type: formConnection.edgeType,
resolve: (obj) => {
return {
node: {
id: obj.id,
name: obj.name,
userId: obj.userId,
widgets: obj.widgets
},
cursor: obj.id
};
}
},
app: {
type: appType,
resolve: () => app
}
},
mutateAndGetPayload: ({
id, name, userId, widgets
}) => {
db.collection('forms').findOneAndUpdate({
_id: new ObjectID(id)
}, {
name, userId, widgets, createAt: Date.now()
});
return {
id, name, userId, widgets
};
}
})
Relay mutation:
export default class ModifyFormMutation extends Mutation {
getMutation () {
return Relay.QL`mutation{modifyForm}`;
}
getFatQuery() {
return Relay.QL`
fragment on ModifyFormPayload {
formEdge
app { forms }
}
`;
}
getCollisionKey() {
return `check_${this.props.app.id}`;
}
getConfigs() {
return [{
type: 'FIELDS_CHANGE',
fieldIDs: {
formEdge: {node: this.props.node},
app: this.props.app.id
}
}];
}
getVariables() {
return {
name: this.props.node.name,
id: this.props.node.id,
userId: this.props.node.userId,
widgets: this.props.node.widgets
};
}
getOptimisticResponse() {
return {
formEdge: {
name: this.props.node.name,
id: this.props.node.id,
userId: this.props.node.userId,
widgets: this.props.node.widgets
}
};
}
}
And error message from browser:
"Variable "$input_0" got invalid value
{"name":"asdfasdfsa","id":"57e790cec252f32aa805e38d","userId":"57e10a02da7e1116c0906e40","widgets":[{"dataID":"client:618507132","label":"sdfas","type":"text","list":[],"description":"","required":true},{"label":"sfasdfasaaa","list":[],"type":"number","description":"","required":"false"}],"clientMutationId":"0"}.↵In
field "widgets": In element #0: In field "dataID": Unknown field."
I have 400,000 lines to enter and I need to break it up. Unfortunately I cannot get this script to exit until it's completed everything. It invariably runs out of memory of course. I thought setting a value at .on('end',function() would be useful but I can't see that value once the .on data has completed.
'use strict';
var mongoose = require('mongoose');
var fs = require('fs');
var parse = require('csv-parse');
var Schema = mongoose.Schema;
var done;
mongoose.connect('mongodb://127.0.0.1:27017/auth');
var userSchema = new mongoose.Schema({
username: {
type: String,
unique: true
},
password: String,
email: {
type: String,
unique: true
},
isActive: String,
roles: {
account: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Account'
}
},
timeCreated: {
type: Date,
default: Date.now
},
search: [String]
});
var accountSchema = new mongoose.Schema({
user: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
name: {
type: String,
default: ''
}
},
isVerified: {
type: String,
default: ''
},
verificationToken: {
type: String,
default: ''
},
name: {
first: {
type: String,
default: ''
},
middle: {
type: String,
default: ''
},
last: {
type: String,
default: ''
},
full: {
type: String,
default: ''
}
},
company: {
type: String,
default: ''
},
phone: {
type: String,
default: ''
},
zip: {
type: String,
default: ''
},
memberid: {
type: String,
default: ''
},
status: {
id: {
type: String,
ref: 'Status'
},
name: {
type: String,
default: ''
},
userCreated: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
name: {
type: String,
default: ''
},
time: {
type: Date,
default: Date.now
}
}
},
userCreated: {
id: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User'
},
name: {
type: String,
default: ''
},
time: {
type: Date,
default: Date.now
}
},
search: [String]
});
var User = mongoose.model('User', userSchema);
var Account = mongoose.model('Account', accountSchema);
fs.createReadStream('./ipart')
.pipe(parse({
delimiter: ','
}))
.on("data-invalid", function(data) {})
.on('data', function(csvrow) {
var u = {
isActive: 'yes',
username: csvrow[0],
email: csvrow[0],
search: [
csvrow[1] + ' ' + csvrow[2],
csvrow[0],
]
};
User.create(u, function(err, createdUser) {
if (err) {
console.log(err);
return;
}
var user = createdUser;
var displayName = csvrow[1] + ' ' + csvrow[2] || '';
var nameParts = displayName.split(' ');
var acct = {
isVerified: 'no',
'name.first': nameParts[0],
'name.last': nameParts[1] || '',
'name.full': displayName,
user: {
id: user._id,
name: user.username
},
search: [
nameParts[0],
nameParts[1] || ''
]
};
Account.create(acct, function(err, account) {
if (err) {
return workflow.emit('exception', err);
}
var fieldstoset = {
roles: {
account: account._id
}
};
User.findByIdAndUpdate(account.user.id, fieldstoset, function(err, user) {
if (err) throw err;
});
});
});
})
.on('end', function() {
console.log('complete');
});
You really need to use bulk inserts, I found this code somewhere and pasting it for you
var Potato = mongoose.model('Potato', PotatoSchema);
var potatoBag = [/* a humongous amount of potato objects */];
Potato.collection.insert(potatoBag, onInsert);
function onInsert(err, docs) {
if (err) {
// TODO: handle error
} else {
console.info('%d potatoes were successfully stored.', docs.length);
}
}
I would recommend you to break down your entire logic of importing your CSV data into these following steps:
1. Write a simple script file which imports the CSV into a temporary collection like this:
YourImportScript
#!/bin/bash
mongoimport -d YourDBName -c YourTempCollectionName --drop --type csv --file pathToYourCSVFile.csv --headerline
2. Run the scripts before creating your Users:
var exec = require('child_process').exec;
function importCSV(callback) {
exec("./pathToYourImportScript/YourImportScript", function (error, stdout, stderr) {
console.log(stdout);
if (error !== null)
console.log('exec error: ' + error);
});
callback()
}
MongoImport will import the CSV pretty quickly.
Get the documents from the temp collection and insert them into your Users Collection.
You can also use async module to control the flow of your code mode neatly:
async.series([
function (callback) {
//CSV Import function
},
function (callback) {
//User Manupulation function
}]);
And it is better to put headers into your CSV columns, as you can create a model when importing documents from the temp collections, and it would be easier to get the properties of users by column headers like username:myCSVModel.username instead of username: csvrow[0].