I want to push an nested element Mongoose.
Check the schema:
const Messages = new mongoose.Schema({
/*[user]*/
author: {
type: Schema.Types.ObjectId,
ref: 'Users'
},
/*[room]*/
room: {
type: Schema.Types.ObjectId,
ref: 'Rooms'
},
message_body: String,
message_status:{type: Boolean, default: false},
created_at: { type: Date, default: Date.now }
});
I want to create a Message with room and Author insert, how to use that?
Imagine you have an 'author' object and a 'room' object. These are going to be the parents. Your message object would be like this:
var newMessage = new Message({author: authore._id, room: room._id, message_body: messageBody ....});
newMessage.save()
.then(() => {
/*** do more things **/
});
Then you will be able to use 'populate' option to make Mongoose refilling author and room fields with the whole objects.
Related
What is the proper way to save an array of data in mongodb using node/mongoose?
I am able to all my data as an array, but everything is saved as the first value in the array (see img)
this is my current code:
const channel = new Channel({
// other fields
fields:req.body.fields,
creator: req.userData.userId //fix: creator not being passed
});
channel
.save()
.then(createdChannel => {
res.status(201).json({
message: "Channel added successfully",
channel: {
...createdChannel,
id: createdChannel._id
}
});
})
.catch(error => {
console.log('error',error)
res.status(500).json({
message: "Creating a channel failed!"
});
});
here is my data model:
const mongoose = require("mongoose");
const channelSchema = mongoose.Schema({
// other fields
fields: { type: [String], required: true },
creator: { type: mongoose.Schema.Types.ObjectId, ref: "User", required: true }
});
module.exports = mongoose.model("Channel", channelSchema);
I didn't see a similar issue online.
Any idea on how I am suppose to save an array properly?
Looks like your req.body.fields is stringified. So, you should parse it back to JSON:
const channel = new Channel({
fields: JSON.parse(req.body.fields),
creator: req.userData.userId,
});
This is because you are setting fields value as an array of strings, regarding to this question you should define your schema as:
fields : [{foo: String, bar: string}]
or if you don't know what attributes you will have in the object:
fields: {"type": Array, "default": []}
Hope this can help you
I have a User schema created with Mongoose that holds a customer array, and inside that customer array there is another fleet array. I have figured out how to push to the customer array within the User schema, however I can not figure out how to loop through the customers, find the customer via id or name, and then push data into the fleet array.
Here is my User schema:
const mongoose = require('mongoose');
const UserSchema = new mongoose.Schema({
username: {
type: String,
default: ''
},
password: {
type: String,
default: '',
},
registerDate: {
type: Date,
default: Date.now()
},
customer: [{
name: {
type: String,
default: '',
},
email: {
type: String,
default: 'No email addresses found',
},
fleet: [{
unitType: {
type: String,
default: 'No type selected',
},
unitNumber: {
type: String,
default: 'No unit number provided',
},
vinNumber: {
type: String,
default: 'No vin number provided'
},
}]
}]
});
module.exports = mongoose.model('User', UserSchema);
I was able to figure out how to push a new customer into the customer array no problem. My problem is I do not get how I can loop through the customer array, and once I find the customer that I need, push data into the fleet array. I am really just stumped on how to word my Google search! Hopefully this is detailed enough, and please let me know if you need to see any other code.
You need to use positional '$' operation. Read here
UserSchema.update(
{'customer.email':'xyz#email.com'},
{
$push:{
'customer.$.fleet':<fleet object>
}
},function(err,result){
})
--- OR ---
UserSchema.update(
{'customer.email':'xyz#email.com'},
{
$set:{
'customer.$.fleet':[fleet array]
}
},function(err,result){
})
Hope this helps.
I have a schema "Reports" that looks like this:
var Reports = new Schema(
{
identifiersub: { // Id of reported submission, populate stuff
type: Schema.Types.ObjectId,
ref: "Submission"
},
identifiercom: { // Id of reported comment, populate stuff
type: Schema.Types.ObjectId,
ref: "Comments"
},
identifieruse: { // Id of reported user, populate stuff
type: Schema.Types.ObjectId,
ref: "AccountDetails"
},
solved: { // Whether this problem has been solved or not
type: Boolean,
default: false
},
processed: [{ // Array of moderators who were participating in processing this report
type: Schema.Types.ObjectId,
ref: "AccountDetails"
}],
type: String, // Type of content. bug, user, submission or comment
reports: [ // Additional text for each type of reported content
{
description: String, // Text from select component. For bugs: the feature that is affected,
reason: String, // Reason for this report
by: { // Reporter
type: Schema.Types.ObjectId,
ref: "AccountDetails"
}
}
],
notes: [{ // Admin notes
title: String, // Fleshed out discussion/reasoning
note: String, // Decided outcome that each note represents
outcome: String, // ("Keep reported", "delete", etc)
date: Date, // Date this note was added
moderator: { // Moderator who added this note
type: Schema.Types.ObjectId,
ref: "AccountDetails"
}
}]
},
{ strict: false, timestamps: true }
)
And in my admin panel I want to implement a search function that searches all reports with the specified keyword. The most important field here is reports: it's an array of objects containing a "by" field which is an ObjectId. Now I wanted to populate the username for this id, but I'm not seeing it in my document...I use the .stream method to check the whole document including nested objects and arrays of objects. Here's my query:
var cursor = Reports
.find({ type: req.query.type})
.limit(500)
.populate("notes.moderator reports.by processed", "username")
.populate("identifieruse", "username dob email ipaddress")
.populate("identifiercom", "by.username comment")
.populate("identifiersub", "meta.title by deleted")
.sort("-createdAt")
.lean()
.stream();
cursor.on('data', function(doc) {
console.log(doc);
if (doc.toString().includes(key)) results.push(doc)
})
cursor.on('error', function(err) {
return catcherror(new Error(err), res)
})
cursor.on('close', function() {
console.log(results);
return res.send(results)
})
Thanks for help!
Use .cursor() instead of .stream() and it works.
I've been struggling with a weird exception and still confused about it after an hour.
CastError: Cast to ObjectId failed for value "pedrammarandi#gmail.com"
at path "_id" for model "Account"
I'm trying to retrieve an Account via email address. Here is my query
export async function getPendingRecipients(user_id, email_address) {
const account = await Account
.find({email: email_address})
.exec();
return true;
}
This is my Schema object
const userGmailSchema = new Schema({
id: {
type: String,
unique: true
},
displayName: String,
image: Object,
accessToken: String,
user: {
type: Schema.Types.ObjectId,
ref: 'User'
},
refreshToken: {
type: String,
default: null
},
email: {
type: String,
unique: true
},
emails: [
{
type: Schema.Types.ObjectId,
ref: 'Emails'
}
]
});
I'm not sure, but I guess the problem is you wrote an id field.
In MongoDB, the "primary key" is _id field, which is an ObjectId object (actually it's a 12-byte-value), and in mongoose, id is a virtual getter of _id, easily said, id is an alias of _id.
(A little different is that, _id returns ObjectId, id returns String version of _id.)
By default, mongoose manage _id field automatically, so commonly we should not write anything about id in schema.
If your id is for something like primary key ID in SQL DB, just remove it from mongoose schema. If it's means something else in your app, try to add an option:
const userGmailSchema = new Schema({
// your schemas here
},
{
{ id: false } // disable the virtual getter
})
or rename it.
http://mongoosejs.com/docs/guide.html#id
Hope this helps.
I have 2 moongose Schema:
var Schema2 = new Schema({
creator : { type: String, ref: 'User'},
schema_name : [{ type: String}],
});
var Schema1 = new Schema({
creator : { type: String, ref: 'User'},
schema_ref : [{ type: String, ref: 'Schema2' }],
});
Would like to know which is the best practice when I create a new Schema1 check that every element of array schema_ref, have the same creator.
Because schema1 elements are added by client form and so i have to check that the schema_ref elements are owned by same User that send the form
You can try with either validator function, or with a simple 'save' middleware:
Schema1.pre('save', function(next) {
let owner;
for (let entry in this.schema_ref) {
if (!owner) {
owner = entry;
} else {
if (entry !== owner) {
return next(new Error("owner mismatch");
}
}
}
});
Also, your schema might not work as you expect it to, it looks like you actually need:
schema_ref: [{
type: {type: String},
ref: "User"
}]
Additionally, take a look at id-validator plugin, or some similar to that - it will, in addition to your validation, also check that all ref-type properties like this actually exist in the other (Users) collection.