I can't save an array of strings into my DB using Mongoose
The schema:
const TrombinoSchema = new mongoose.Schema({
Name: [String]
});
const Trombino = mongoose.model('Trombino', TrombinoSchema);
and for save:
var trombino = new Trombino ({
Name: req.query.name
});
trombino.save(callback);
Array.isArray(req.query.name) => true;
I tried different statement
Name: [{type : String}] , Name: [{type : String}] or Name: []
but in my DB i found the empty Array
In the trombino schema you need to change the name field:
const mongoose = require('mongoose');
const TrombinoSchema = new mongoose.Schema({
Name: {type:[String]}
});
const Trombino = mongoose.model('Trombino', TrombinoSchema);
let trombinoItem = new Trombino({
Name: ['test name 1','test name 2','test name 3']
});
trombinoItem.save().then((result)=>{
console.log(result);
});
Here the print of execution:
This the data in the database. You can see the name as a array of string:
Related
This question already has answers here:
pushing object into array schema in Mongoose
(2 answers)
Closed 5 years ago.
I have a mongoose schema inbox-model:
var schema = mongoose.Schema({
email: String,
data: [{
from: String,
to: String,
msg: String
}]
})
var Inbox = module.exports = mongoose.model('Inbox',schema);
module.exports.addData = function(inbox, callBack){
inbox.save(callBack);
}
I need to add to data[] array for a specific email when there's new data for that email address.
I can add data this way, through my router by calling:
var Inbox = require('inbox-model');
var inbox = new Inbox({
email: 'some#email.com',
data:[{
from: 'from',
to: 'to',
msg: 'msg'
})
Inbox.addData(inbox, Inbox);
though it doesn't add to data[] but keeps adding a whole row.
Help is much appreciated, I've searched for similar questions, but I couldn't find on adding data, just creating models with arrays.
This question has been answered a lot of time on StackOverflow. However, I'm answering it again
// Schema File - userSchema.js
const userSchema = new Schema({
email: { type: String, required: true },
data: [{
from: String,
to: String,
msg: String
}]
})
const user = mongoose.model('user', userSchema)
module.exports = user
// Service File
const user = require('./userSchema')
function someFunction(email, from, to, message) {
user.findOne({ email: email }, function(err, document) {
if (document) {
document.data.push({
from: from,
to: to,
msg: message
})
document.save(function(err) {
err != null ? console.log(err) : console.log('Data updated')
})
}
})
}
I'm creating the schema for a mongo document and I can do everything except prevent duplicates in a non-object array.
I'm aware of the addToSet, but I'm referring to Mongo Schema.
I don't want to check on Update using $addToSet, rather I want this to be part of my schema validation.
Example below.
let sampleSchema = {
name: { type: 'String', unique: true },
tags: [{ type: 'String', unique: true }]
}
The above snippet prevents name from having duplicate values. It allows tags to be stored as a string array.
But.. I cannot limit the array to be unique strings.
{ name: 'fail scenario', tags: ['bad', 'bad', 'array']}
I'm able to insert this record which should be a fail scenario.
const express = require('express');
const router = express.Router();
const mongoose = require('mongoose');
const _ = require('underscore');
let sampleSchema = new mongoose.Schema({
name: {
type: 'String',
unique: true
},
tags: [{
type: 'String'
}]
})
sampleSchema.pre('save', function (next) {
this.tags = _.uniq(this.tags);
next();
});
const Sample = mongoose.model('sample', sampleSchema, 'samples');
router.post('/sample', function (req, res, next) {
const sample = new Sample(req.body);
sample.save()
.then((sample) => {
return res.send(sample);
})
.catch(err => {
return res.status(500).send(err.message);
})
});
I've come to the conclusion that this is impossible to do via Mongoose Schema.
JSON schema is done like so.
let schema = {
name: { type: 'string' }
tags: {
type: 'array',
items: { type: 'string', uniqueItems: true }
}
}
I'll validate with JSON schema before creating Mongo Document.
This method builds on Med's answer, handles references, and done completely in scheme validation.
let sampleSchema = new mongoose.Schema({
strings: [{type: 'String'}],
references: [{type: mongoose.Schema.Types.ObjectId, ref: 'Reference'],
});
sampleSchema.pre('save', function (next) {
let sample = this;
sample.strings = _.uniq(sample.strings, function(i) {return (i._id) ? i._id.toString() : i;});
sample.references = _.uniq(sample.references, function(i) {return (i._id) ? i._id.toString() : i;});
return next();
});
I'm a little late, but maybe this will help someone in the future.
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
name: {
type: String,
},
reference: {
type: [mongoose.Schema.Types.ObjectId],
ref: 'SomeOtherSchema',
// Add a custom validator.
validate: {
// The actual validator function goes here.
// "arr" will be the value that's being validated (so an array of
// mongoose new ObjectId statements, in this case).
validator: arr => {
// Convert all of the items in the array "arr", to their string
// representations.
// Then, use those strings to create a Set (which only stores unique
// values).
const s = new Set(arr.map(String));
// Compare the Set and Array's sizes, to see if there were any
// duplicates. If they're not equal, there was a duplicate, and
// validation will fail.
return s.size === arr.length;
},
// Provide a more meaningful error message.
message: p => `The values provided for '${ p.path }', ` +
`[${ p.value }], contains duplicates.`,
}
},
});
The above commented code should be pretty self explanatory.
With the newer version(s) of MongoDB, you can use $addToSet to append to an array if and only if the new value is unique compared to the items of the array.
Here's the reference: https://www.mongodb.com/docs/manual/reference/operator/update/addToSet/
Here's an example:
const SampleSchema = new mongoose.Schema({
tags: [String]
});
const Sample = mongoose.model('Sample', SampleSchema);
// append to array only if value is unique
Sample.findByIdAndUpdate({_id: 1, {$addToSet: {tags: "New Tag"}}});
This will effectively update the tags if the "New Tag" is not already present in the tags array. Otherwise, no operation is done.
I have a model which looks like this:
User.js
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var memberSchema = new Schema({
email: {
type: String,
required: true,
unique: true
},
password: {
type: String,
required: true,
min: 8
}
});
var userSchemaPrimary = new Schema({
team_code : {
type: String,
required: true,
unique: true
},
members:[memberSchema],
});
var User = mongoose.model('User', userSchemaPrimary);
module.exports = User;
And this is how am trying to save
var User = require('../models/user');
var newTeam = new User({
team_code : 'CODE01',
members:
{
email: req.body.email,
password: pass
}
});
newTeam.save(function(err) {
if (err) throw err;
console.log('User saved successfully!');
return res.send("Done");
});
When executed, throws model validation error.
Well I tried to save data without the array documents, then its saves successfully. But when I try to save the array (array "members"), it throws validation error.
I WANT TO
Store data in the following way:
{
team_code: "CODE01",
members: [
{
email: "test01#email.com",
password: "11111111"
},
{
email: "test02#email.com",
password: "22222222"
}
{
email: "test03#email.com",
password: "33333333"
}
]
}
I dont understand what is going wrong. Any help is appreciated.
You are assigning object to members field, but it's an array
var newTeam = new User({
team_code : 'CODE01',
members: [{
email: req.body.email,
password: pass
}] // <-- note the array braces []
});
I am trying to add an array to a Mongo document, and I'm getting the error "Cast to Array failed for value "[object Object],[object Object]" at path "vendors""
Here is my model:
module.exports = {
attributes: {
vendors: {
type: [String]
},
description: {
type: String
}
}
};
Here is my code to create:
var vendors = ko.observableArray(['foo','bar']);
var desc = ko.observable('yadda yadda yadda');
var dto = {
data: {
vendors: vendors(),
description: description()
}
};
DataService.quoteRequest.create(dto);
Musical Shore,
I'm not familiar with knockout.js, but in regards to Mongoose it doesn't look like you are defining your Schema and Model. You would need to do the following:
Define Schema
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var attributesSchema = new Schema({
vendors: [String],
description: String
});
Create a Model
var Attributes = mongoose.model('Attribute',attributesSchema);
Create and Save a Document
//create an attribute document
var attribute = new Attributes(
{
vendors: vendorsArray,
description: desc
}
);
attribute.save(function(err){
if(!err) console.log('Success');
}
I am building a mean stack app with express and mongoose. I have two schemas, userSchema and courseSchema:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var courseSchema = mongoose.Schema({
title:{type:String, required:'{PATH} is required!'},
featured:{type:Boolean, required:'{PATH} is required!'},
published:{type:Date, required:'{PATH} is required!'},
courseLink:{type:String, required:'{PATH} is required!'},
user: [{type:Schema.Types.ObjectId, ref : 'User'}]
});
var Course = mongoose.model('Course', courseSchema);
module.exports = Course;
var userSchema = mongoose.Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
username: {
type: String,
required: true,
unique: true // creates unique index inside MongoDB
},
salt: {type: String, required: true},
hashed_pwd: {type: String, required: true},
roles:[String],
courses:[{type: Schema.ObjectId,
ref: 'Course' }]
});
I am able to create users and and courses (as an admin). What I want to do now is to allow each user add a course to his list of courses (or just click a 'like' button beside the course and that course would be added to his profile).
On the side of the controller, I have tried to check for the user id from the session, find that user and add the course to his document. But that's where I am stuck,
exports.addMyCourse = function(req, res){
console.log('user id', req.session.passport.user);
console.log('id', req.body._id);
var currentUserId = req.session.passport.user;
User.findOne({'_id':currentUserId}, function(err, doc){
console.log(doc);
});
Most of the solutions I looked at are not very clear about this. Any help would be appreciated.
RESOLVED:
I used $addToSet to add the course objects into the courses array inside the User model:
This might be useful for people searching for similar soutions:
My User schema:
var userSchema = mongoose.Schema({
firstName: {type: String, required: true},
lastName: {type: String, required: true},
username: {
type: String,
required: true,
unique: true // creates unique index inside MongoDB
},
salt: {type: String, required: true},
hashed_pwd: {type: String, required: true},
roles:[String],
courses:[{
type:Schema.ObjectId, ref:'Course'
}]
});
var User = mongoose.model('User', userSchema);
My Course schema:
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
var courseSchema = mongoose.Schema({
title:{type:String, required:'{PATH} is required!'},
featured:{type:Boolean, required:'{PATH} is required!'},
published:{type:Date, required:'{PATH} is required!'},
courseLink:{type:String, required:'{PATH} is required!'}
});
var Course = mongoose.model('Course', courseSchema);
Inside my controllers folder, I have users.js and courses.js:
In the courses.js file, I created the addMyCourses middleware to update the User model's courses array by first retrieving the current user's id from the session and using $addToSet to insert the object and avoid duplicates at the same time. Also I made sure I am adding only the ObjectId's of the courses and not the entire course document so I won't have future problems with too much data in one document:
exports.addMyCourse = function(req, res){
var myCourse = {
title: req.body.title,
featured: req.body.featured,
published: req.body.published,
courseLink: req.body.courseLink
};
var currentUserId = req.session.passport.user;
var courseId = req.body._id;
User.update({_id:currentUserId},
{$addToSet: {"courses": courseId}},
{safe: true, upsert: true, new : true},
function(err, model) {
console.log(model);
}
);
};
Since I only had the ObjectId's of the courses inside the courses array of the User model, I had to use mongoose's populate() method to do a joint query on both models so that I get the corresponding course documents of the ids.
In users.js file:
exports.getUserCourses = function(req, res, next){
var currentUserId = req.session.passport.user;
User.findById(currentUserId).populate('courses')
.exec(function(err, data){
if(err) {
console.log(err);
}
console.log('user courses', data);
res.send(data);
})
};