I'm working with Mongodb, and was wondering on how to get records made by the user. In the below example I have to records each with different emails (createdBy), but how do I get the records by the current user logged in?
Schema result:
var resultSchema = new Schema({
test: { type: String, required: true, lowercase: true},
status: { type: String, required: true, lowercase: true},
date: { type: Date, required: true},
amount: { type: Number, required: true},
createdBy: { type: String, required: true},
});
Schema user:
var userSchema = new Schema({
email: { type: String, required: true, lowercase: true},
username: { type: String, required: true, lowercase: true},
password: { type: String, required: true}
});
Database:
"recipe": [
{
"_id": "5b7af572a1051b1b18aec627",
"test": "asassdasdasd",
"status": "waiting",
"date": "2018-08-06T22:00:00.000Z",
"amount": 2,
"createdBy": "test#outlook.com",
"__v": 0
}
]
"recipe": [
{
"_id": "5b7af572a1051b1b18aec621",
"test": "test2",
"status": "waiting",
"date": "2018-08-06T22:00:00.000Z",
"amount": 2,
"createdBy": "notTest#outlook.com",
"__v": 0
}
]
I tried this, but this returns empty:
router.get('/userResults', (req, res) => {
Result.find({createdBy: req.body.createdBy}, (err, result) => {
})
})
To say the user is logged in or not and to identify the user who is logged in, I am sure you have some mechanism to get the Email ID of the current user.
So ideally you should have access to the Email ID of the user who is logged in and making the API call.
Provision a middleware to parse the email id from every request instead of making a Database call to check the user's email ID.
Query : db.resultSchema.find({createdBy: parsed_email_id_from_api_request}
One way to do it using JWT is parse the token using a middleware and forwarding the email or any other relevant field to the request where you make the Database call to check the "results" collection.
Related
I'm trying to use refPath to reference which collection to pull the population data from inside my schema, and even though it looks identical to the examples I've seen, its just not working.
Here is my schema for statesPersons, not super important, but it contains the activeWork array of objects.
import mongoose, {model, Schema} from "mongoose";
const statesPersonsSchema = new Schema(
{
profileId: {
type: String,
required: true,
unique: true,
},
department: {
type: String,
required: true,
index: true,
},
firstName: String,
lastName: String,
location: String,
org: String,
title: String,
jobDescription: String,
email: {
type: String,
lowercase: true,
},
phoneNumber: String,
activeWork: ["activeWork"],
emailList: [String],
jobAssignments: [String],
affiantInfo: {
affiantInfoTitle: String,
affiantInfoExperience: String,
},
assessments: [
{
assessdBy: {
type: Schema.Types.ObjectId,
ref: "statesPerson",
},
dueDate: Date,
questions: {},
},
],
},
{ strictPopulate: false }
);
export default mongoose.model("statesPersons", statesPersonsSchema);
Here is my schema for activeWork, the array of objects. This has the referenceId that I need to populate as well as the collectionType which I pull what collection it is from.
import mongoose, {model, Schema} from "mongoose";
const activeWorkSchema = new Schema(
{
active: Boolean,
collectionType: {
type: String,
enum: ["messages", "cases"],
},
referenceId: {
type: Schema.Types.ObjectId,
refPath: "collectionType",
},
sentBy: {
type: Schema.Types.String,
ref: "statesPersons",
},
sentTo: {
type: Schema.Types.String,
ref: "statesPersons",
},
timeRecived: Date,
dueDate: Date,
subject: String,
viewed: Boolean,
content: {},
},
{ strictPopulate: false }
);
export default mongoose.model("activeWork", activeWorkSchema);
And here is my query.
export async function getStatesPersonsActiveWorkByProfileId(req, res){
mongoose.set('debug', true);
try{
const { profileId } = req.params
const data = await statesPersons
.find({ profileId })
.populate('statesPersons.activeWork.referenceId')
.exec()
return res.send({
message: "success",
data: data,
status: 200 })
}catch(e) {
console.error(e.message)
return res.send({
message: "couldn't fetch active work",
data: null,
status: 500 })
}
}
its returning with the statesPersons object and the activeWork contains the objectId I need to populate, but its not populating. it looks like this.
"activeWork": [
{
"active": true,
"collectionType": "messages",
"referenceId": "63a49e3052658ce60c1dafcb",
"sentBy": "108416469928574003772",
"dueDate": "2018-02-21T11:16:50.362Z",
"subject": "testing",
"viewed": false,
"_id": "63a49e3052658ce60c1dafce"
I can force it to work by changing the query to be explicit.
const data = await statesPersons
.find({ profileId })
.populate({path: 'activeWork.referenceId', model: 'messages'})
.exec()
which looks like this.
activeWork": [
{
"active": true,
"collectionType": "messages",
"referenceId": {
"_id": "63a49e3052658ce60c1dafcb",
"involvedParties": [
"108416469928574003772",
"100335565301468600000"
],
"comments": [
{
"sender": [
"108416469928574003772"
],
"dateSent": "2022-12-22T18:13:04.604Z",
"content": "There is no way this is going to work.",
"_id": "63a49e3052658ce60c1dafcc"
}
],
But this wont work because I need it to be able to pull what model to use from the collectionType field
sorry for the late response , it seems like you are trying to populate the multilevel documents multilevel population.
here is an example.
db.statesPersonsSchema.find({ profileId }). populate({
path: 'activeWorkSchema',
populate: { path: 'referenceId' }
});
I've been writing a lot of MySQL lately so I've forgotten how to write some Mongoose queries. I am trying to search my database to find stocks where the user is the same as the req.params.user. below is the route and my Schema so you can see what's going on. I'm running it in Post man, but it's giving me a "Cannot GET /stock/user-stocks/Sina" Error. I also left a sample stock in my DB for reference
router.get('user-stocks/:user', (req, res) => {
Stock.find({ user: toString(req.params.user)})
.then((stocks) => res.json(stocks))
.catch(err => res.json(err))
})
const stockSchema = new Schema({
user: {type: String, required: true},
symbol: {type: String, required: true},
target: {type: Number, required: false},
stop: {type: Number, required: false},
description: {type: String, required: false},
date: {type: Date, required: false}
})
{
"_id": "5ff284d07b93cd434cae9a08",
"user": "Sina",
"symbol": "AAPL",
"target": 200,
"stop": 100,
"description": "Get money",
"date": "2021-01-03T00:00:00.000Z",
"__v": 0
},
I have the following Model-Structure
[{
"orders":
[{
"_id": "5f24839133759d4859ef5233",
"owner": {
"_id": "5f17fdb08145508a94fc1bda"
},
}]
},
...
]
I want to get all objects that have an order with a specific owner id.
I tried find({"orders.owner._id": "5f17fdb08145508a94fc1bda" }) which just returns an empty array.
Tried many other variations also without dot-notation, but nothing worked.
I'm using mongoose to query the MongoDB database.
EDIT:
These are the Mongoose Schemata used for the collection:
const orderPoolShema:mongoose.Schema = new mongoose.Schema({
orders: [{type: mongoose.Types.ObjectId, ref: 'Order' }]
},
{
timestamps: true
});
const orderShema:mongoose.Schema = new mongoose.Schema({
owner: {type: mongoose.Types.ObjectId, ref: 'User', require },
},
{
timestamps: true
});
const userShema:mongoose.Schema = new mongoose.Schema({
firstname: {type: String, required: true},
lastname: {type: String, required: true}
},
{
timestamps: true
});
And this is my Node.js code:
OrderPool.find({"orders.owner._id": mongoose.Types.ObjectId("5f17fdb08145508a94fc1bda") })
.then((orderPools:any) => {
res.send(orderPools);
}).catch((err:any) => {
res.status(500).send({
message: err.message || "Some error occurred while retrieving orderPools."
});
});
Any ideas on how to get that query to work are very appreciated.
Thanks for your help.
Using mongoose you can create a sub document as such:
export const UserSchema = new Schema({
email: {
type: String,
unique: true,
required: "email is required.",
match: [/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/, 'Please fill a valid email address']
},
firstName: {
type: String,
required: "firstName is required."
},
lastName: {
type: String,
required: "lastName is required."
},
dateOfBirth: {
type: Date,
required: "dateOfBirth is required."
},
roles: [{
role: String,
required: "role is required",
validate: isValidUserRole
}],
address: AddressSchema,
});
Address Schema
export const AddressSchema = new Schema({
streetAddress: {
type: String
},
addressLine2: {
type: String
},
city: {
type: String
},
state: {
type: String
},
zipCode: {
type: String
},
country: {
type: String
}
});
Whenever I save a user, will mongoose create a new user document with nested address data or a user and address and then reference that address document within the user instance?
How would I approach the case of 2 users sharing the same address?
Thanks!
You need not to provide the AddressSchema in the UserSchema schema.
You can just provide reference of AddressSchema like the following.
export const UserSchema = new Schema({
email: {
type: String,
unique: true,
required: "email is required.",
match: [/^\w+([\.-]?\w+)*#\w+([\.-]?\w+)*(\.\w{2,3})+$/, 'Please fill a valid email address']
},
firstName: {
type: String,
required: "firstName is required."
},
lastName: {
type: String,
required: "lastName is required."
},
dateOfBirth: {
type: Date,
required: "dateOfBirth is required."
},
roles: [{
role: String,
required: "role is required",
validate: isValidUserRole
}],
address: {type:mongoose.Schema.Types.ObjectId,ref:'AddressSchema',required:true}
});
But remember that in order to make this work, 1st you need to create an Address data and provide their _id in UserSchema.
What happens by the above method is,
AddressSchema's ObjectId(_id) works as the REFERENCE in UserSchema. Basically, it acts as a REFERENCE DOCUMENT in UserSchema
You can find this out by querying your data through mongo shell.
When a document contains an embedded document (this is indistinguishable from nested hashes in the shell), the embedded document wholly belongs to the top level document and cannot be included-by-reference into another document.
all.
I am writing a MEAN stack application, using Mongoose (4.0.6) with Node/Express to interface with MongoDB, and I am running into difficulty populating saved documents when I later save new documents that the existing document should have a reference to. Specifically, in the app I have a user create an instance of a company before creating their admin account for that company, so when the user registers him/herself as an admin, I'd like the company document to populate its users array with the new user.
Here are my schemas for company and user:
User.js...
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.Types.ObjectId;
var userSchema = new Schema({
first_name: { type: String, required: '{PATH} is required!' },
last_name: { type: String, required: '{PATH} is required!' },
username: { type: String, required: '{PATH} is required!', lowercase: true, unique: true },
password: { type: String, required: '{PATH} is required!' },
roles: { type: [String] },
company: { type: ObjectId, ref: 'Company', required: true },
db_permissions: [{ type: ObjectId, ref: 'DataConnection' }],
created_by: { type: ObjectId, ref: 'User' },
created_at: { type: Date, default: Date.now },
updated_at: [{ type: Date, default: Date.now }]
});
var User = mongoose.model('User', userSchema);
module.exports = {
User: User
};
Company.js...
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.Types.ObjectId;
var companySchema = new Schema({
name: { type: String, uppercase: true, required: '{PATH} is required!', unique: true },
industry: { type: String, required: '{PATH} is required!' },
phone: { type: String, required: '{PATH} is required!' },
address_line_1: { type: String, uppercase: true, required: '{PATH} is required!' },
address_line_2: { type: String, uppercase: true },
city: { type: String, uppercase: true, required: '{PATH} is required!' },
state_prov: { type: String, uppercase: true, required: '{PATH} is required!' },
postal_code: { type: String, required: '{PATH} is required!' },
country: { type: String, required: '{PATH} is required!' },
logo_url: String,
users: [{ type: ObjectId, ref: 'User' }],
data_connections: [{ type: ObjectId, ref: 'DataConnection' }],
created_at: { type: Date, default: Date.now },
updated_at: [{ type: Date, default: Date.now }]
});
var Company = mongoose.model('Company', companySchema);
module.exports = {
Company: Company
};
Here is the code in my controller:
User.create(userData, function(err, user) {
if(err) {
if(err.toString().indexOf('E11000') > -1) {
err = new Error('Duplicate email');
}
res.status(400);
return res.send({ reason:err.toString() });
}
console.log('company id: ' + user.company);
Company.findById(user.company)
.populate({path: 'users'})
.exec(function (err, company) {
if (err) return handleError(err);
console.log(company.name + '\'s users now includes ' + company.users);
});
res.send(user);
The company (e.g. TEST53) saves to the database correctly with an empty users array:
{
"_id": "55ae421bf469f1b97bb52d5a",
"name": "TEST53",
"industry": "Construction",
"phone": "2352626254",
"city": "GDFGD",
"country": "United States",
"address_line_1": "DSGDFGH",
"state_prov": "GF",
"postal_code": "45645",
"logo_url": "",
"__v": 0,
"updated_at": [
"2015-07-21T12:59:07.609Z"
],
"created_at": "2015-07-21T12:59:07.597Z",
"data_connections": [],
"users": []
}
Then when I create the user, it saves correctly:
{
"_id": "55ae4238f469f1b97bb52d5b",
"username": "test53#test.com",
"password": "$2a$12$ZB6L1NCZEhLfjs99yUUNNOQEknyQmX6nP2BxBvo1uZGlvk9LlKGFu",
"company": "55ae421bf469f1b97bb52d5a",
"first_name": "Test53",
"last_name": "Admin",
"__v": 0,
"updated_at": [
"2015-07-21T12:59:36.925Z"
],
"created_at": "2015-07-21T12:59:36.550Z",
"db_permissions": [],
"roles": [
"admin"
]
}
And I can see that the correct ObjectId prints to the console for user.company:
company id: 55ae421bf469f1b97bb52d5a
But the company's users array doesn't populate with the user's id, and the console.log inside the .exec function prints 'TEST53's users now includes '.
I have tried several ways of wiring this up, with just 'users' instead of { path: 'users' }, writing a function that pushes the user into the array, using .run instead of .exec, but so far without success.
Is there something obvious I'm missing? Thanks in advance for any suggestions!
You're not actually adding the user to the company.
Try this:
Company.findById(user.company, function (err, company) {
if (err) return handleError(err);
// Add the user to the company's list of users.
company.users.push(user);
// Need to save again.
company.save(function(err) {
if (err) return handleError(err);
console.log(company.name + '\'s users now includes ' + company.users);
});
});
res.send(user);
It seems to me that all you want to do is to update the Company model to add the user, as opposed to actually use the (populated) Company document as a response, so I left out an additional Company.findById(...).populate(...) call.