MongoDB/GraphQL: Model.find() to get posts that userId is in likes - javascript

in my resolvers I have a method to find user likes with
async function userBookmarks(args, context) {
const user = checkAuth(context);
const posts = await Post.find({likes: {userId: user.id}})
return posts; }
But GraphQL returns an empty array.
For reference, the Post model is
likes: [
{
userId: String,
createdAt: String
}],

I came across a similar problem and fixed it by defining the MongoDB Collection name in the bottom of my MongoDB Schema.
const UserSchema = new mongoose.Schema({
firstName: {
type: String,
required: true
},
lastName: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
location: {
type: String,
required: false
}
}, { collection : 'Users' });
EDIT:
Use $elemMatch to query several fields.
const posts = await User.find({likes: {$elemMatch: {userId: user.id}}})

Related

Mongoose text index on array of subdocuments always returns nothing

I have a collection of documents for users to track companies that looks like this:
const mongoose = require("mongoose");
const TrackingListSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "users",
required: true,
index: true
},
email: {
type: String,
required: true,
},
companies: [{
country: {
type: String,
required: true
},
countryCode: {
type: String,
required: true
},
name: {
type: String,
required: true
}
}]
});
TrackingListSchema.index({"companies.name": "text"});
module.exports = mongoose.model("trackinglist", TrackingListSchema);
As you can see, I am creating a text index on the "companies.name" field.
However, when I run a query as such:
TrackingList.aggregate([
{$match: {
"companies.countryCode": "us",
$text: {
$search: "Some Company",
$caseSensitive: false
}
}},
{$project: {
_id: 0,
email: 1,
}}
])
Nothing is returned even though I am sure that at least one tracking list has a company with that name. What am I doing wrong? Am I creating the text index wrong because it is inside an array? I thought I had this working but now I just can't get it to work.

changing array inside the collection mongoDB

I am trying to change an array in my collection of users according to the id of an object I have in my array
it looks like this
_id:60a54bb0a5c5d25c9f4b83ea
email:"timotej"
pass:"$2b$10$hdvMb.PrcRmwNCqxcLpOmOLTvRTrMzHWAhPHWa4o4E.qOfuDTjeAm"
createdAt:2021-05-19T17:32:32.792+00:00
updatedAt:2021-05-23T11:32:37.882+00:00
__v:0
contacts:Array
0:Object
_id:"60aa3d3db9344014e5944291"
name:"contact1"
email:"contact1#mail.com"
phone:"0"
1:Object
_id:"60aa3d55b9344014e5944292"
name:"contact2"
email:"contact2#mail.com"
phone:"00"
Shema:
const mongoose = require('mongoose')
const Schema = mongoose.Schema;
const userSchema = new Schema({
email: {
type: String,
required: true,
unique: true
},
pass:{
type: String,
required: true
},
contacts:{
_id: {
type: String,
unique: true
},
name:{
type: String,
},
email:{
type: String
},
phone:{
type: String
}
}
}, {timestamps: true})
const User = mongoose.model('User', userSchema)
module.exports = User;
here is my code, I am trying to find the user by its email, and then the object in array contacts by its id and then update the contact.
const user = User.findOneAndUpdate(
{ email: mail.toLowerCase(), "contacts._id": req.params.id},
{ $set:{
"contacts.$._id": req.params.id,
"contacts.$.name": req.body.name,
"contacts.$.email": req.body.email,
"contacts.$.phone": req.body.phone,
}
},
{ multi: false }
).then((result) => {
console.log("result : " + result)
the data in req should be ok, but nothing is changing in my db when i send request

Unable to get _id which is not ObjectID with mongoose

I can't access to _id of any mongoose.model object. I know there are a lot of similar answers but none of it solved my problem. I am using mongoose and TypeScript.
I've existing collection which contains data with existing Mixed _id:
{
_id: 10,
name: "someString",
email: "someString",
}
...
I've Schema and interface:
const UserModel: Schema = new Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
});
export interface IUser extends Document {
name: string;
email: string;
}
export default mongoose.model<IUser>('User', UserModel);
and I try to select some user:
UserModel.findOne({email:data.email}).then((user)=>{
console.log(user);
// I get everything without _id
// { name: "someString", email: "someString" }
console.log(user.id);
// null
});
Another attempt
I've also tried to set _id to false in options:
const UserModel: Schema = new Schema({
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
}, { _id: false });
and I tried to select some user:
UserModel.findOne({email:data.email}).then((user)=>{
console.log(user);
// I get everything with _id
// { _id: 10, name: "someString", email: "someString" }
console.log(user.id, user._id);
// but it is not accessible
// null, undefined
});
Note
If I create document record through mongoose it creates _id as ObjectId() and it is selectable.
Mongoose expects an ObjectID for _id
Add your custom type to the schema
const UserModel: Schema = new Schema({
_id: { type: mongoose.Schema.Types.Mixed, required: true },
name: { type: String, required: true },
email: { type: String, required: true, unique: true },
});
The _id index can't be modified so don't worry about adding index options.
It's usually best to leave Mongo to use it's ObjectID.

How do you save certain items for specific users in mongodb?

I'm working on a job tracker app.
User creates an account, saving the user in a mongodb collection.
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});
const JobSchema = new mongoose.Schema({
position: {
type: String,
required: true
},
company: {
type: String,
required: true
},
status: {
type: String,
default: "applied"
},
date: {
type: Date,
default: Date.now
}
});
When a user adds a job, how would you store (.post) and retrieve (.get) that data to correspond to that specific user only?
Is there a way to save the users "_id" to the jobs added, and searchById to get the jobs?
It depends what exactly you want to achieve meaning what type of relationships your models will have. Lets say your users will have multiple jobs the best approach would be to store an array of ObjectIds. The refoption tells mongoose which collections to search during population of the array
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
},
jobs: [{type:Schema.Types.ObjecId,ref: 'Job'}]
});
and then when you query the database you chain populate('jobs') after the query.
You can read more on the subject here
For example,
const UserSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
password: {
type: String,
required: true
},
date: {
type: Date,
default: Date.now
}
});
const User = mongoose.model('User', UserSchema);
async function updateUser() {
let user = await User.findOne({"name": "a-unique-user-name-in-the-db"})
let userId = user._id
let newEmail = "asdf#asdf.com"
let updated = await User.updateOne(
{ "_id": userId },
{
$set: {
"email": newEmail,
}
}
)
if (updated) {
console.log("updated")
}
}
updateUser();

Nested associations for multiple accounts

I am trying to associate various login methods with the same User model in mongo.
const UserSchema = new Schema({
email: String
isVerified: { default: false, type; Boolean }
accounts: {
ref: 'Account',
type: Schema.Types.ObjectId
}
})
const AccountSchema = new Schema({
facebook: {
ref: 'FacebookAccount',
type: Schema.Types.?
},
local: {
ref: 'LocalAccount',
type: Schema.Types.?
},
twitter: {
ref: 'TwitterAccount',
type: Schema.Types.?
},
})
const LocalAccount = new Schema({
email: String,
name: String,
phone: String,
password: String,
_user: {
ref: 'User',
type: Schema.Types.ObjectId
}
})
What I would like to get the data coming back to me looking like would be:
{
_id: '12345789',
email: 'turdFerguson#gmail.com',
accounts: {
facebook: { ... }
local: { ... }
}
}
I'm really unsure about these associations though hence Schema.Types.? on the individual accounts. Also unsure if I should be using embedded vs object reference and where is appropriate. I'm going in circles trying to get the associations to match up.
I suggest you keep it simple with embedded.
Here is a quick suggestion:
const UserSchema = new Schema({
isVerified: {
default: false,
type: Boolean
},
accounts: {
local: {
email: String,
name: String,
phone: String,
password: String
},
facebook: {
// fields related to Facebook
},
twitter: {
// fields related to Twitter
}
}
})
I removed email as it seems redundant to have it since you already have accounts.local.email

Categories

Resources