mongoose findOne method is returning null - reactjs

I am following this tutorial. Even though code is exactly what is mentioned in the tutorial, every time i run the graphql mutation query to update a particular tweet, it returns null and logs null on cmd.
I verified mongoose version is same (4.11.3).I believe something is wrong with findOne method as even in deleteTweet resolver, findOne is returning null. Is it because findOne needs a callback? but in the tutorial there is no callback passed. I also noticed that findOneAndUpdate works fine but it creates a new entry rather updating the existing tweet.
updateTweet: async (_, { id, ...rest}, { user }) => {
try {
await requireAuth(user)
const tweet = await Tweet.findOne({ id, user: user.id });
console.log(tweet);
if(!tweet) {
throw new Error('Not Found!');
}
return tweet.save();
} catch (e) {
throw e;
}
},
deleteTweet: async (_, { id }, { user }) => {
try {
await requireAuth(user);
const tweet = await Tweet.findOne({ id, user: user.id });
if(!tweet) {
throw new Error('Not Found !')
}
await tweet.remove();
return {
message: "Deleted Tweet Successfully"
}
}catch(error) {
throw error;
}
}
}
TweetSchema
import mongoose, { Schema } from 'mongoose';
const TweetSchema = new Schema({
text: {
type: String,
minlength: [5, 'Text need to be longer'],
maxlength: [144, 'Text is too long'],
},
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
favoriteCount: {
type: Number,
default: 0
}
}, { timestamps: true})
export default mongoose.model('Tweet', TweetSchema);

You have a typo. In MongoDB, the key field is _id NOT id. This is added automatically by MongoDB unless provided, so you need to change your code to use _id instead.

Related

RTK Query failing to fetch new data after mutation

I'm trying to use RTK query to fetch data from Firestore using the queryFn. The problem I'm having is that I'm developing a multiwizard, where the fields in the form are initialised with data straight from RTK Query.
Update an input field with a mutation in step 1
Go to step 2
Go back to step 1 (fetch is rejected with a ConditionError, please see attached log)
export const userApi = createApi({
reducerPath: 'userApi',
baseQuery: fakeBaseQuery(),
tagTypes: ['User'],
endpoints: builder => ({
getUser: builder.query<Customer, string>({
async queryFn(userId) {
try {
const docSnapshot = await getDoc(doc(db, 'users', userId));
const customer = docSnapshot.data() as Customer;
return { data: customer };
} catch (err) {
return { error: err };
}
},
providesTags: (result, error, arg) => [{type: 'User', id: result.id }]
}),
updateUser: builder.mutation<{ success: boolean }, { userId: string; user: Partial<UserInfo> }>({
async queryFn(payload) {
const { userId, user } = payload;
try {
// Note: Id is same for both. Have also tried replacing with 'LIST'
const res = await updateDoc(doc(db, 'users', userId), { ...user });
return { data: { success: true } };
} catch (err) {
return { error: err ? err : null };
}
},
invalidatesTags: (result, error, { userId }) => [{ type: 'User', id: userId}],
})
})
});
export const { useGetUserQuery, useUpdateUserMutation } = userApi;
I've also tried just using User for the providesTag/invalidatesTags.
I'm trying to figure out why the 2nd query, after going back to step 1 of the form fails to retrieve the data I've just updated.
I fixed this issue by updating rtk from 1.8.5 to 1.9.0
Seems like there was a bug
invalidateTags works correctly when dealing with persisted query
state.
https://github.com/reduxjs/redux-toolkit/releases/tag/v1.9.0

Mongoose/Mongodb getting .deleteOne is not a function

When I click to delete a post, my console is saying TypeError: post.user.posts.deleteOne is not a function. It giving me this error after deleting.
const post = await Post.findByIdAndDelete(id).populate('user'); This code I am deleting the post from Post Schema
await post.user.posts.deleteOne(post)This code is to delete the post from the User Schema. I populated user and assigned it to post and then delete the user's post from this code, but I'm getting the error here.
Below is the controller code
export const deletePost = async (req, res) => {
const { id } = req.params;
try {
const post = await Post.findByIdAndDelete(id).populate('user');
await post.user.posts.deleteOne(post)
if (!post) {
return res.status(500).json({ message: "Unable To Delete" })
}
res.status(200).json({ message: "Deleted Successfully" })
} catch (error) {
console.log(error);
}
}
Client side delete request
const handleDeleteTrue = async () => {
try {
const { data } = await api.delete(`/post/${id}`)
console.log(data)
window.location.reload();
} catch (error) {
console.log(error.response.data.message);
}
};
User model schema
import mongoose from 'mongoose';
const userSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
username: {
type: String,
required: true,
unique: true
},
email: {
type: String,
required: true,
unqie: true
},
password: {
type: String,
required: true,
minlength: 6
},
posts: [{ type: mongoose.Types.ObjectId, ref: "Post", required: true }]
});
export default mongoose.model('User', userSchema);
Im able to delete the post from the post model schema, but in this pic, which shows the user model schema, that same post that was deleted is not deleted here. This is the problem Im trying to solve.
What I can seem to understand in your function below is that you're trying to delete a single post and also checking if post exists first
export const deletePost = async (req, res) => {
const { id } = req.params;
try {
const post = await Post.findByIdAndDelete(id).populate('user');
await post.user.posts.deleteOne(post)
if (!post) {
return res.status(500).json({ message: "Unable To Delete" })
}
res.status(200).json({ message: "Deleted Successfully" })
catch (error) {
console.log(error);
}
}
I'd suggest you try this
export const deletePost = async (req, res) => {
const { id } = req.params;
try {
//check if document exists in mongoDB collection
if (!mongoose.Types.ObjectId.isValid(id)) {
return res.status(500).json({ message: "Unable To Delete" }) }
await Post.deleteOne(id)
res.status(200).json({ message: "Deleted Successfully" })
catch (error) {
console.log(error);
}
}
I found out the answer. My user model schema for post was an array so I had to use $pull to delete it.
This is the code that worked for me
await post.user.posts.pull(post)
await post.user.save()
You can't use findOneAndDelete on populate to delete one object from an array. it doesn't work that way. Use This Instead.
const result = await User.findOneAndUpdate(
{ _id: Id },
{ $pull: { post:PostId } },
{ new: true }
);
You can find More on Pull and Push Operations on BlogLink

How to make the mongoose update array work properly?

this is my schema.it has a user field and an array of object which contains a text message and direction will hold a either sent or received value.
const MessageSchema = new mongoose.Schema({
user:{type: String,required: true},
textArray:[
{
text:{type: String,required: true},
direction:{ type: String,required: true }
}]
});
This is the router code.btw should there be double quotes on the keys in var textmessage?
router.post('/',async(req,res)=>{
const {user,text,direction}=req.body;
const errors = validationResult(req);
if (!errors.isEmpty()) {
return res.status(400).json({ errors: errors.array() });
}
var textmessage={
"text":text,
"direction":direction
}
const doc = await Message.updateOne(
{ user: user },
{ $set: { user:user,$push:{textArray:textmessage}} },
{ upsert: true },
function(err,result){
if (err){
console.log(err);
}
else{
console.log(result)
res.send(result)
}// Make this update into an upsert
});
})
this is how it showsup in mongodb.the user is working ok but when i click theres is nothing under textArray.What am I doing wrong exactly?
you are using await with callback function , which is wrong :
const filter = { user: user };
const update = { $push:{textArray:textmessage}};
let doc = await Message.findOneAndUpdate(filter, update, {
new: true,
upsert: true
});
console.log('doc=',doc);

Creating GraphQL Search query using React Native

I am trying to implement a search query to help me search by name or category. I need help with only the backend part of it which is setting up the resolver and the index which im not sure if I m doing it right
Resolver.js
//search for single user
user: async ({_id}) => {
try {
const foundUser = await User.findOne({_id: _id})
return foundUser;
} catch (err){
throw err;
}
},
//search for all users
users: async () => {
try{
const users = await User.find()
return users;
} catch(err) {
throw err;
}
},
I want to be able to search all users with the role "Star" and do the search only on those users. Not really sure where to go from here
Index.js
type User {
_id: ID!
username: String
password: String
name: String
role: String
enterCategory: String
}
//not sure if search is right
type RootQuery {
user(_id: ID!): User!
users: [User!]!
searchStars(search: String): [Users]!
}
Index.js
searchCategories(search: String): [User]!
Resolver
searchCategories: async ({ search }) => {
try {
const users = await User.find()
return users.filter(x => x.enterCat === search);
} catch (err) {
throw err;
}
}

Get inserted document directly in RethinkDB

I have been starting with RethinkDB. I have gone through the documentation. I have a simple use case of returning the inserted document when a POST call is made. This is something I have done so far.
router.post('/user', jsonParser, async (req: Request, res: Response) => {
const connection = await conn;
const { name, email, employeeId } = req.body;
// Email is primary key
consumerTable.insert({
name,
email,
employeeId,
}).run(connection, (err: any, result: any) => {
if (err) {
throw err;
} else {
consumerTable.get(email).run(connection, (innerErr: any, userResult: any) => {
if(innerErr) {
throw innerErr;
} else {
res.send({
data: {
...userResult
},
responseCode: 200,
});
}
});
}
});
});
Is there any way to get the inserted object in the insert result itself. I read a lot of documentation, but didn't find anything useful.
Any help would be great. Cheers!
You may use the returnChanges option of the insert command as specified in the documentation. It should look like this:
consumerTable.insert({
name,
email,
employeeId,
}, { returnChanges: true }).run(connection, async (err: any, cursor: any) => {
const data = await cursor.toArray();
// .error should be undefined, unless... an error happened!
// not sure about the format though, console.log data to check it really is an array
res.send({ data: data[0].new_val, error: data[0].error });
});

Resources