AngularJS Mongoose findOne OK but save error :DocumentNotFoundError: - angularjs

On client.save() below, I have the following error (which is catch properly):
DocumentNotFoundError: No document found for query "{ _id: '5bfbce595be7d1047c976e6b' }"
app.put('/api/client', function (req, res) {
Client.findOne(new mongoose.Types.ObjectId(req.body._id)).then(client => {
//This is OK, I can see client and its properties
client.name = req.body.name;
//This is OK, I can see the updated client and its properties
client.save().then(test => {
console.log("ERR=" + err);
console.log(test);
}).catch(err => console.log("ERR :" + err));
res.json(client);
});
});
The model is as such:
mongoose.model('Client', {
_id: {type: String, default: ''},
name: {type: String, default: ''},
creationDate: {type: Date, default: ''}
});
How come the document is found on FindOne() and no more on save()?

try to do so:
mongoose.model('Client', {
_id: { type: mongoose.Schema.Types.ObjectId, auto: true },
name: { type: String, default: '' },
creationDate: { type: Date, default: Date.now() }
});
And
Client.findOne().where({_id : req.body._id})...

Related

Pushing Array of object from react to mongodb+express server issue

I'm store array of object but it is giving mer following error.
(node:87929) UnhandledPromiseRejectionWarning: ValidationError: Place validation failed: placesToVisit: Cast to embedded failed for value "[{"name":"xczc","location":"zczxc","description":"czxczx"}]" (type string) at path "placesToVisit" because of "ObjectParameterError"
here is my schema:
placesToVisit: [
{
name: {
type: String,
required: [true, "Please enter the place's name"],
},
description:{
type: String,
required: [true, "Please enter the place's description"],
},
location:{
type: String,
required: [true, "Please enter the place's location"],
}
},
],
here is my contoller:
exports.createPlace = async (req, res) => {
try {
const newPlace = await new Place({
placesToVisit:req.body.placesToVisit,
});
newPlace.save()
debugger
res.status(201).json({
success:true,
message:"Place Created Successfully",
newPlace
})
} catch (error) {
return res.status(500).json({
success:false,
error:error.message
})
}
};
here is my formdata structure:
data.append("placesToVisit",JSON.stringify(values.placesToVisit))
here is ss of yaload
You must convert the string to an array:
placesToVisit: JSON.parse(req.body.placesToVisit),

how to insert checkbox as array into mongodb

I don't know why it's not being inserted. it doesn't show an error or anything so i couldn't figure out the problem.
the tags [ '61c2102d165a5af742091a70', '61c37621165a5af742093a1a' ].
here is my insert function:
insert: async(req,res)=> {
const {userid,tags}=req.body;
console.log("userid", userid)
console.log("tags", tags) //tag [ '61c2102d165a5af742091a70', '61c37621165a5af742093a1a' ]
try {
User.findByIdAndUpdate(
userid,
{ $push: { tags: {$each : tags } }} ,
);
return res.status(200).send({msg:"success"});
} catch (error) {
console.log(error);
res.status(500).send({ msg: "Something went wrong" });
}
}
my user schema:
tags: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Tag'
}]
tag schema:
const TagSchema = new Schema({
name: {
type: String
},
type: {
type: Object,
},
timestamp: {
type: Date,
default: Date.now
},
});
Most codes i saw do it like that but i couldn't figure out why mine isn't working
Since you are using async, you can make use of await to see it if is saved or not. Rewriting logic in this way you can catch saved instance and return success or failure.
insert: async(req,res)=> {
const {userid,tags}=req.body;
console.log("userid", userid)
console.log("tags", tags) //tag [ '61c2102d165a5af742091a70', '61c37621165a5af742093a1a' ]
const doc = await User.findByIdAndUpdate(
userid,
{ $push: { tags: {$each : tags } }} ,{new:true}
);
if (!doc) return res.status(500).send({ msg: "Something went wrong" });
return res.status(200).send({msg:"success"});
}

CastError: Cast to ObjectId failed for value "{ _id: ':5ec5cc919efcf581eb692690' }" at path "_id" for model "Posts"

Checking the router on the server side it console logs the right values, only the follow error is popping up in here. Trying to build a counter that should update the value on the backend. But the problem I have is that value will not be stored in there. When using Postman the value will be stored successfully. What is the solution that can fix this issue.
export const incrementProduct = (index, updateAmount, id) => {
return dispatch => {
dispatch(increment(index));
try {
axios.patch(`${API_URL}/:${id}`, {
amount: updateAmount
}).then(res => {
console.log(res.config);
})
} catch(err) {
console.log(err)
}
}
}
const PostSchema = mongoose.Schema({
title: {
type: String,
required: true
},
description: {
type: String,
required: true
},
amount: {
type: Number,
required: true
},
editable: {
type: Boolean,
required: true
},
data: {
type: Date,
default: Date.now
}
});
// update
router.patch('/:postId', async(req, res) => {
console.log('update', req.params.postId + 'amount ' + req.body.amount)
try {
const updatedPost = await Post.findByIdAndUpdate(
{_id: req.params.postId}, <--- this cause the console error...
{$set:
{
amount: req.body.amount
},
})
console.log('try')
res.json(updatedPost)
} catch(err) {
console.log(err + 'test ')
res.json({ message: err })
}
})
You need to remove : in the patch url like this:
axios.patch(`${API_URL}/${id}`
Also findByIdAndUpdate requires only the value of _id, so you can only pass the value like this:
await Post.findByIdAndUpdate(req.params.postId, ...
findByIdAndUpdate(id, ...) is equivalent to findOneAndUpdate({ _id: id }, ...).

Apollo graphql is returning null data for an empty subdocument in mongodb

I added another field(contacts) to my apollo graphql mutation but when retrieving the field it produces false data. Even if the matching mongodb field has real data or not, graphql returns mutliple fields with null values.
I've already tried removing __typename in the apollo client graphql options but it doesn't help. Current stack is:
reactjs 16.8.5
react-apollo 2.5.2
mongodb 3.6.11
mongoose 5.3.6
apollo-server 2.3.1
I don't understand why it does this since I have another subdocument that is almost identical but returns correctly.
// CLIENTSIDE
// APOLLO SETUP
const cache = new InMemoryCache({
dataIdFromObject: object => object.key || null
})
const AuthLink = (operation, forward) => {
const token = cookies._uid
operation.setContext(context => ({
...context,
headers: {
...context.headers,
authorization: token
}
}))
return forward(operation)
}
const httpLink = new HttpLink({
uri:"/graphql",
credentials: "include"
})
// mutation
export const LOGIN_MUTATION = gql`
mutation loginMutation($email: String!, $password: String!) {
login(input: {email: $email, password: $password}) {
token
user {
_id
contacts { // This is the subfield in question
_id
username
}
subscriptions { // This subfield returns corretly
_id
title
levels {
_id
}
}
}
error {
path
message
}
}
}
`
// SERVERSIDE
// APOLLO SETUP
const baseSchema = `
schema {
query: Query,
mutation: Mutation
}
`
const schema = makeExecutableSchema({
typeDefs: [
userTypeDefs,
],
resolvers: merge(
{},
userResolvers,
)
})
const {ObjectId} = mongoose.Types
ObjectId.prototype.valueOf = function() {
return this.toString()
}
export default new ApolloServer({
introspection: true,
credentials: true,
schema,
context: ({req, res}) => ({
url: req.protocol + "://" + req.get("host"),
req
})
})
// USER MONGOOSE MODEL
export const UserSchema = new mongoose.Schema(
{
contacts: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "User"
}
],
firstName: {
type: String
},
lastName: {
type: String
},
username: {
type: String,
lowercase: true,
unique: true,
required: [true, "can't be blank"],
match: [/^[a-zA-Z0-9]+$/, "is invalid"],
index: true
},
sentRequests: [
{
username: {
type: String,
default: ""
}
}
],
subscriptions: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Course"
}
],
password: {
default: "",
required: [true, "can't be blank"],
type: String
}
},
{timestamps: true}
)
UserSchema.plugin(uniqueValidator, {message: "is already taken."})
export default mongoose.model("User", UserSchema)
// USER GRAPHQL SCHEMA
type User {
_id: ID
contacts: [User]
email: String!
username: String
subscriptions: [Course]
createdAt: String
updatedAt: String
}
type AuthPayload {
token: String
user: User
error: [Error]
}
input LoginInput {
email: String!
password: String!
}
type Mutation {
login(input: LoginInput): AuthPayload
}
// USER RESOLVER
const login = async (parent, args, ctx, info) => {
let email = args.email
let user = await User.findOne({email})
.populate("subscriptions")
.populate("contacts")
.exec()
if (!user) {
arrayOfErrors.push({
path: "email",
message: "invalid email"
})
} else if (user) {
console.log("user: ", user)
return {
user,
error: arrayOfErrors
}
}
Mutation: {
login
}
// CONSOLE LOG CLIENTSIDE
user:
confirmed: true
contacts: Array(3) // returns an array of 3 items?? It's [] in mongodb
0: {_id: null, username: null}
1: {_id: null, username: null}
2: {_id: null, username: null}
length: 3
__proto__: Array(0)
subscriptions: Array(1)
0: {_id: "5cd36fc1c8d1e222b99d9c58", title: "Korean Class 101 Study",
length: 1
__proto__: Object
__proto__: Object
// CONSOLE LOG SERVERSIDE
POST /graphql 200 64.359 ms - -
user: {
contacts: [ ],
subscriptions:
[ { _id: 5cd6f7f8212af32c75555d4b,
subscribers: 2,
owner: 5cd36edec8d1e222b99d9c57,
createdAt: 2019-05-09T00:09:37.845Z,
updatedAt: 2019-05-11T16:36:14.661Z,
__v: 23 } ],
password: '$2b$10$bkjiazklcoqlkJSJSAioxoAqkoajsdjnqjkiaallaadfadfp7zS',
_id: 5cd36edec8d1e222b99d9c57,
email: 'example#test.com',
username: 'example',
createdAt: 2019-05-09T00:05:50.314Z,
updatedAt: 2019-05-29T17:23:21.545Z,
__v: 32
}
I expected an empty array to return [ ], instead graphql returns an array of 3 items with null values. Even if I add real contacts into the database it still returns the 3 items with null values.
The subscriptions are returning correctly yet it is almost identical to the contacts field with the exception of being a type "Course" in the mongoose model instead of type "User".
I doubt anyone will ever come across this type of error, but here's the solution in case you do. During development I had placed this code in my resolver for testing purposes. Removing it solved the problem.
// USER RESOLVER
...
Query: {...},
/* code to remove
User: {
contacts: user => {
return ["Mo", "Larry", "Curly"]
}
}
*/
Mutation: {...}
A very trivial thing but having not been in this actual code for several months made it difficult to spot. I never thought the 3 stooges would ever give me so much headache.

Mongoose/Mongo: Update Not Saving

I'm extremely perplexed by this issue that I'm having with mongo/mongoose. I'm essentially trying to get an array of products, delete a certain product from the array, and then update the shopping chart with the new array that omits the selected product. Here's the snippet of code I'm dealing with:
const remove = (req, res, next) => {
console.log('here is the product id ' + req.body.cart.product)
delete req.body._owner // disallow owner reassignment.
Cart.find({_id: req.user.cartId})
.then((products1) => {
console.log("array of products: " + products1[0].product)
const index = products1[0].product.indexOf(req.body.cart.product)
console.log("index valeu: " + index)
if (index > -1) {
products1[0].product.splice(index, 1)
return products1[0].product
}
return products1[0].product
})
.then((products2) => {
console.log('Second Promise Input: ' + products2)
Cart.update({_id: req.user.cartId}, {$set: {product: products2}})
})
.then(() => res.sendStatus(204))
.catch(next)
}
And here's the output from my server:
Server listening on port 4741
here is the product id 5952b57ea52d092b8d34c6b0
array of products: 5952b57ea52d092b8d34c6b0,5952b57ea52d092b8d34c6b0,5952b57ea52d092b8d34c6b0,5952b57ea52d092b8d34c6b0,5952b57ea52d092b8d34c6b0
index valeu: 0
Second Promise Input: 5952b57ea52d092b8d34c6b0,5952b57ea52d092b8d34c6b0,5952b57ea52d092b8d34c6b0,5952b57ea52d092b8d34c6b0
PATCH /carts-decrease/595b037e128cfd37e0c864d7 204 38.773 ms
According to my console.logs, I'm getting the array just the way I want it but it simply does not update the shopping cart with the new array. I've been staring at this code for far too long and I'd appreciate a second set of eyes on this. Thanks.
P.S. Ignore the fact that the product ids are all the same, its just a testing variable
Cart Schema:
'use strict'
const mongoose = require('mongoose')
const cartSchema = new mongoose.Schema({
product: {
type: Array,
required: false
},
owner: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: false
}
}, {
timestamps: true,
toJSON: {
virtuals: true,
transform: function (doc, ret, options) {
const userId = (options.user && options.user._id) || false
ret.editable = userId && userId.equals(doc._owner)
return ret
}
}
})
const Cart = mongoose.model('Cart', cartSchema)
module.exports = Cart
Product Schema:
'use strict'
const mongoose = require('mongoose')
const productSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
price: {
type: Number,
required: true
},
description: {
type: String,
required: true
}
}, {
toJSON: {
virtuals: true
}
})
const Product = mongoose.model('Product', productSchema)
module.exports = Product
Show request:
const show = (req, res) => {
const product = {}
product.array = []
// console.log(req.cart.product)
const promises = []
Promise.all(req.cart.product.map(function (id) {
return Product.find({_id: ObjectId(id)})
})).then(function (products) {
console.log(products)
req.cart.product = products
return res.json({
cart: req.cart.toJSON({virtuals: true, user: req.user})
})
}).catch(function (err) {
console.log(err)
return res.sendStatus(500)
})
}
I would recommend you to slightly modify your cartSchema and store products in the form of an array of embedded documents:
const cartSchema = new mongoose.Schema({
products: [{
name: { type: String },
price: { type: Number }
...
}]
...
});
If you do this you can simply use the $pull update operator to remove products from your cart:
{ $pull: { <field1>: <value|condition>, <field2>: <value|condition>, ... } }
In your case the query should then look like this:
Cart.update(
{ _id: req.user.cartId },
{ $pull: { products: { '_id': req.body.cart.product } }}
);
As the embedded documents will have their own ObjectId there will only be one document matching the query.

Resources