GraphQL check for unique record on mutation - mongodb

On a GraphQL mutation, how can I check in the resolve function if the record I´m trying to create is unique ?
Consider the code:
const createUser = {
type: UserType,
description: 'Creates an user',
args: {
data: {
name: 'user',
type: new GraphQLNonNull(UserInputType)
}
},
resolve(root, args) {
let data = args.data;
UserModel.findByName(data.name);
??? How can I return an error here if there is a user with
??? the given name already stored in database ?
const model = new UserModel(data);
model.save();
}
}
Should I keep that logic on the GraphQL Server or should I leave it to the database layer. If I leave it to the database layer, how can I return the database error to my client, so that he knows he´s trying to create an invalid user ?
I´m the following stack: MongoDB, express, Mongoose, graphql-js on server, ReactJS and Relay on client.

Related

Sign Up not working and throwing params errors

I am currently able to sign in just fine with previously created user credentials and use the app as normal, but am unable to create a new user. I am using React.js on the client side and an Express api on the backend. I am getting a mongoose validation error. All of the authentication came with the template the course has us use and I haven't touched any of those files. I even went back and compared commit history trees to ensure that nothing was changed.
Here is my user schema and sign-up route. I tried eliminating uniqueness from the model and that didn't impact it. I know there is a lot of potential places something could be going wrong, but if anyone has any suggestions on potential issues I would be forever grateful! I console logged the req.body.credentials within sign up and the data being sent over looks good.
Error code: 422 Unprocessable Entity
Server side error: 'The received params failed a Mongoose validation'
const mongoose = require('mongoose')
const { petSchema } = require('./pet.js')
const { pictureSchema } = require('./picture.js')
const userSchema = new mongoose.Schema({
email: {
type: String,
required: true,
unique: true
},
hashedPassword: {
type: String,
required: true
},
token: String,
pets: [petSchema],
pictures: [pictureSchema]
}, {
timestamps: true,
toObject: {
// remove `hashedPassword` field when we call `.toObject`
transform: (_doc, user) => {
delete user.hashedPassword
return user
}
}
})
module.exports = mongoose.model('User', userSchema)
// SIGN UP
// POST /sign-up
router.post('/sign-up', (req, res) => {
// start a promise chain, so that any errors will pass to `handle`
console.log(req.body.credentials)
Promise.resolve(req.body.credentials)
// reject any requests where `credentials.password` is not present, or where
// the password is an empty string
.then(credentials => {
if (!credentials ||
!credentials.password ||
credentials.password !== credentials.password_confirmation) {
throw new BadParamsError()
}
})
// generate a hash from the provided password, returning a promise
.then(() => bcrypt.hash(req.body.credentials.password, bcryptSaltRounds))
.then(hash => {
// return necessary params to create a user
return {
email: req.body.credentials.email,
hashedPassword: hash
}
})
// create user with provided email and hashed password
.then(user => User.create(user))
// send the new user object back with status 201, but `hashedPassword`
// won't be sent because of the `transform` in the User model
.then(user => res.status(201).json({ user: user.toObject() }))
// pass any errors along to the error handler
.catch(err => handle(err, res))
})
Solved. One of the subdocuments I had within user had a key with a value set to unique. I needed to eliminate that because my database was indexing users with a null value and throwing a duplicate error. I then needed to reset my database (I just renamed it to test it out) so that it didn't have any saved indexes with that configuration. I just deleted my collections within Heroku as well (luckily I didn't have significant amounts of data in there and this solution was perfectly fine for my situation). I am now able to sign up users again without any duplicate key errors.

How to Connect/Query Mongoose to an existing Database

I am working on trying to connect a Node/Express server to an existing MongoDB Database/Collection. I have already successfully connected to the database. However, I am having a tremendously difficult time setting up my models/schema to query.
The MongoDB is MongoDB Atlas and has one collection with over 800,000 documents. The name of the single collection is "delitosCollection".
I have tried the following to with no success:
var CrimeData = mongoose.model('DelitosCollection', new Schema({}),'delitosCollection');
mongoose.connection.on('open', function(ref){
console.log("connected to the mongo server");
CrimeData.find({}, (err,results) => {
if(err){
console.log("ERROR")
throw err
}
console.log("results: ", results.length)
} )
});
I know the connection is working as I am receiving the console.log with no errors. However, results.length is returning 0 when it should be over 800,000. Have spent way too many hours on this.
Create an empty schema for each collection you want to use
and then create a model to be used in your project
the model take 3 parameter
1)name of the model
2)schema name
3)collection name ( from mongodb atlas)
like that
const mongoose = require('mongoose');
mongoose.connect('mongodb uri')
const userSchema = new mongoose.Schema({});
const User = mongoose.model('User', userSchema, 'user');
then you can use the model normally
User.find({})
connection to mongo db
// Connect to mongoDB
mongoose.connect('mongodb://localhost/[yourDbName]',{useNewUrlParser:true})
.then(function(){
console.log('mongoDB connected');
})
.catch(function(){
console.log('Error :');
})
after that you will have to create your schema and then only you can query the database
create your schema like this
// Crimes Schema
const CrimeDetailsSchema= new Schema({
first_name: {
type: String,
required: true
},
last_name: {
type: String,
required: true
},
email: {
type: String,
required: true
}
});
const Profile = module.exports = mongoose.model('delitosCollection', CrimeDetailsSchema, 'delitosCollection');
after that create your queries
you can get an idea about that in mongoose documentation here
You can refer to the answer given below, just pass an empty object in schema
like db.model('users', new Schema({}))

Create temp sails model

For unit test I need to create temp model object without saving it in DB, just to have some instance method.
Example of model structure
//User.js - my model
module.exports = {
attributes: {
firstName : { type: 'string' },
lastName : { type: 'string' },
getName: function () {
return this.firstName + ':' + this.lastName;
}
}
};
I have next object
const testData = {
firstName: 'Foo',
lastName: 'Bar'
};
This line creates new record in db
User.create(testData);
Is it possible to avoid record creation? How can I do it?
To answer your initial question, functionality to switch off or on whether Sails actually creates a record in your database when you call Model.create() to the best of my knowledge does not exist, without a workaround as you have or I have described in the comments.
With that said, Sails does offer a simple solution for testing and development purposes.
As a convenience during development, Sails provides a built-in database adapter called sails-disk. This adapter simulates a real database by reading and writing database records to a JSON file on your computer's hard drive.
If you are using a Sails version of < v1 see documentation:
Add a connection to the database in config/connection.js
localDiskDb: {
adapter: 'sails-disk'
},
In the model you are testing, point the model towards the sails-disk connection.
...
module.exports = {
connection: "localDiskDb",
attributes: {
...
If you are using Sails version >= v1 see documentation:
Instead, add sails-disk as a datastore in config/datastores.js
localDiskDb: {
adapter: 'sails-disk'
},
And in the model you are testing, as above, point the model towards the sails-disk datastore.
...
datastore: 'localDiskDb',
...

How can i use MongoDB with Cloud Functions for Firebase?

I want to use Cloud Functions for Firebase and MongoDB. The problem is I don't know how to connect my Mongo database with Cloud Functions. My database is deployed at matlab.
I made this schema:
var mongoose = require('mongoose')
var Schema = mongoose.Schema
var patientSchema = new Schema({
name: {
type: String,
required : true,
},
disease:{
type: String,
required : true,
},
medication_provided: {
type: String,
required : true,
},
date : {
type : Date,
}
})
const patient = mongoose.model('patientInfo', patientSchema)
module.exports = patient
Then I require my schema in project index.js file, and export a function called getAllPatient.
const patient = require('../Patient')
const functions = require('firebase-functions');
const mongoose = require('mongoose')
mongoose.connect('mongodb://patient:patient123#ds139869.mlab.com:39869/patient',{useMongoClient: true})
exports.getAllPatient = functions.https.onRequest((request, response) => {
patient.find({}).then((data) => {
response.send(data)
})
})
but gives me an error that "Error: could not handle the request"
I was recently facing this type of error and found that firebase free plan doesn't allow the outbound connections from within the functions. If you need to call external http/tcp connections, you are required to be on the flame or blaze plan. see the screenshot attached below or see the section cloud functions -> outbound networking at this link Firebase Pricing
Try to design the cloud function in a similar way shown in a link below:-
https://github.com/firebase/functions-samples/blob/master/authorized-https-endpoint/functions/index.js
I've tried with mongoose long time back and it was working fine and but it's slow because for every new request it's going to open the mongoose connection and serve you the data.
Hope this helps!!

Cannot use Collection as Model PhalconPHP

I'm trying to setup MongoDB collection for my PhalconPHP application.
I have the mongo and collectionManager set up.
$di->set('collectionManager', function(){
return new Phalcon\Mvc\Collection\Manager();
}, true);
//MongoDB Database
$di->set('mongo', function() {
$mongo = new MongoClient("localhost:27017");
return $mongo->selectDb("test");
}, true);
I have a model
class User extends \Phalcon\Mvc\Collection {
....
}
Then I got this error
Unexpected value type: expected object implementing Phalcon\Mvc\ModelInterface, object of type MyApp\Models\User given
Disclaimer: This was extracted from the question.
I was using Model validation instead Validation in the model body.