Here is an example schema:
var schema = mongoose.Schema;
var userSchema = new schema ({
username: {type: String},
hobby: [{
indoor: {
type: {type: String},
description: {type: String}
},
outdoor: {
type: {type: String},
description: {type: String}
}
}]
});
module.exports = mongoose.model('User', userSchema);
So, a very simple schema. It asks for a user name, and then it asks for a user to list their hobbies, and is split between indoor and outdoor hobbies, and inside of an array.
Using body-parser, I could get to a user name in a form input like this:
var user = new User();
user.username = req.body.username;
That's simple enough. But how do I get to the hobbies inside of the array? I've tried doing:
user.hobby.indoor.type = req.body.type
But this doesn't work; it just gives me an error. Any help would be appreciated.
The following code will help you access your key properly. As hobby is an array, you need to provide an index for fetching its objects. Dot notation works with objects
user.hobby[0].indoor.type
Js Fiddle: https://jsfiddle.net/x18nyd2e/
So I did end up finding the answer to my problem. Here is an example of what to do:
var user = new User();
user.username = req.body.username;
user.hobby = {{
indoor: {
type: req.body.type,
description: req.body.description
}
}];
And that's how you can get to a property inside of an array.
Related
I have a variation on the question asked and solved by #Guilherme here but my recursive embedded documents are within another schema like this;
var mongoose = require('mongoose');
var CollectPointSchema = new mongoose.Schema({
name: {type: String},
collectPoints: [ this ]
});
var GroupSchema = new mongoose.Schema({
label: {type: String},
points: [CollectionPointSchema]
});
const Group = mongoose.model("Group", GroupSchema);
I'd like to modify the solution that Guilherme proposed here but not sure how to go about it.
The main problem was that the child folders were not being populated with the name: field. I think because that field is not in the top level of the schema. So as a work-around I have added the name: field to the parent schema like this;
var GroupSchema = new mongoose.Schema({
label: {type: String},
name: {type: String},
points: [CollectionPointSchema]
});
and I also needed to change the order of Guilherme's solution from this;
var FolderModel = mongoose.model('folders', FolderSchema);
FolderSchema.pre('save', function(next) {
if (this.isNew) {
recursive_reference(FolderModel, this, "folders")
}
next();
});
to this;
FolderSchema.pre('save', function(next) {
if (this.isNew) {
recursive_reference(FolderModel, this, "folders")
}
next();
});
var FolderModel = mongoose.model('folders', FolderSchema);
The result is that I have an unused field at the parent level, but it works.
I am learning MongoDB and mongoose at the moment. I have a Archive and a User schema in mongoose:
archive.js
var mongoose = require('mongoose');
var User = require('../users/user');
var notesSchema = new mongoose.Schema({
author: User.userId,
text: String,
files:[String]
});
var archiveSchema = new mongoose.Schema({
name: String,
priority: String,
deadline: Date,
status: String,
assigned_memnbers: [User.userId],
notes: [notesSchema],
});
archiveSchema.virtual('archiveId').get(function() {
return this._id;
});
module.exports = mongoose.model('Archive', archiveSchema);
user.js:
var mongoose = require('mongoose');
var userSchema = new mongoose.Schema({
username: String,
mail: String,
bio: String,
password: String
});
userSchema.virtual('userId').get(function() {
return this._id;
});
module.exports = mongoose.model('User', userSchema);
When I run my server i get the error
TypeError: Invalid value for schema path `author`, got value "undefined"
The the problem comes from author: User.userId, but I don't know how to make a reference between the two tables.
For reference, here is what my complete db design more or less looks like:
Any input on how to solve this problem or improve the overall design is welcome. Thanks you.
I think what you're talking about is a reference to other collection:
author: { type: Schema.Types.ObjectId, ref: 'User' }
and
assigned_members: [{ type: Schema.Types.ObjectId, ref: 'User' }]
should work fine.
Source: Mongoose population
I faced the same issue.I had imported a module, It was just not exporting from another module. so I have added:
exports.genreSchema = genreSchema;
I've got two models in mongoose:
const user = mongoose.Schema({
name: String,
...
});
and
const moderator = mongoose.Schema({
name: String,
...
});
When I access these collections with:
user.find()
I get in response list of users and moderators separetly.
What I want to achive is to join these two list together to get a list based on this model:
const myDataSchema = mongoose.Schema({
user: {type: Schema.Types.ObjectId, ref: 'user'},
moderator: {type: Schema.Types.ObjectId, ref: 'moderator'}
});
Where one of attributes (either user or moderator) will be set.
I solved my problem. Instead of using the mongoose schema I created my "own object". My code:
let list= [];
users.forEach( function (user)
{
list.push({user: user});
});
moderators.forEach( function (moderator)
{
list.push({moderator: moderator});
});
It's probaly not the most efficient way but it works.
I'm using a couple of one-to-many models and was wondering what the advantage of having both an array of "children" ObjectID()s and a "parent" model's ObjectID() in the child is. For example:
// a client will have a new card every ten visits
var ClientSchema = new Schema({
first_name: String,
last_name: String,
email: String,
cards: [] // ObjectID()s, <--- is this necessary?
});
var CardSchema = new Schema({
client: ObjectID(), // <--- or is this enough?
visits: []
});
I think the client: ObjectID() should do the trick in most cases, specially with the Population options Mongoose offers.
It suffices to store the reference ObjectId in one of the documents.
As you can read in the documentation or in this answer, the reference field needs a type and a ref. The name of field is arbitrary. Once you have done this and registered your models, you can use the models to populate your queries.
var clientSchema = new Schema({
first_name: String,
last_name: String,
email: String
});
var cardSchema = new Schema({
client: {
type: Schema.Types.ObjectId,
ref: 'client'
}
});
// models
var Card = mongoose.model('Card', cardSchema);
var Client = mongoose.model('Client', clientSchema);
Yet, it could be helpful to store an array of ObjectId's. However, this also creates a huge window for mistakes. A mismatch of foreign key and primary key, in SQL dialect. You can always do a count query if you need to count. I would say, do either the above or do this:
var clientSchema = new Schema({
first_name: String,
last_name: String,
email: String,
cards: [
{
type: Schema.Types.ObjectId,
ref: 'card'
}
]
});
var cardSchema = new Schema({
card_name: String
});
// models
var Card = mongoose.model('Card', cardSchema);
var Client = mongoose.model('Client', clientSchema);
I use Mongoose and Passport in my web application for the addition of new users into my MongoDB database. I use Google oauth for registering/signing in. In my user schema, I have the following defined for the google method:
//user.js
var userSchema = mongoose.Schema({
google : {
id : String,
token : String,
access_token : String,
email : String,
name : String,
picture : String,
nameInfo : Object,
}
});
I use the following method for user creation:
//passport.js
var newUser = new User();
//newUser.google.token = token;
newUser.google.name = profile.displayName;
newUser.google.nameInfo = profile._json.name
newUser.google.email = profile.emails[0].value;
newUser.google.id = profile.id;
newUser.google.picture = profile._json.image.url + '0';
newUser.google.access_token = token;
You can see that all this data goes under the "google" array in the top level of my user document. How would I add a new, complex, static array? For example, I want a new array at the top level of document in the following format:
newUser.dogs = ["cats":[]}]
I need this particular format based on a dependency in how users should look in my web code. I will eventually be adding data to the "cats" array, but it needs to start out empty. When I try varations of this, I'm only able to get the top level array - ex: my document looks like:
objectid: 1000,
google: [...],
dogs: []
when I need it to look like:
objectid: 1000,
google: [...],
dogs: [{"cats":[]}]
What do I need to change to my schema, either on the schema design, or the data going into the schema?
You want to set inner embedded docs.
Here it is sample, You can create it like this.
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var Trigger = new Schema({
type : {type: String},
value: {type: Number}
});
var Field = new Schema({
label : {type: String},
type: {type: String},
triggers: [Trigger]
});
var Form = new Schema({
fields : [Field],
user_id : {type: String}
});