my schema in node js
var itemSchema = new mongoose.Schema({
name: { type: String, required: true },
value: { type: String }
});
while doing find, the following result comes,
Item.find().exec(callback); gives result
[{"one":1},{"two":2},{"three":1},{"four":1}]
but i want the result like this,
[{"one":1,"two":2,"three":3,"four":4}]
Is there only way iterate and form the result ?
Please suggest me!
Related
I would like to know how I can verify if a value is in an array of a different value in the schema. Have a look at this example:
const progressSchema = mongoose.Schema({
possible_statuses: {
type: Array
},
first_status: {
type: String
}
});
And a POST (insert) example of this would be:
{
possible_statuses: ['Untouched', 'In Progress', 'Complete'],
first_status: 'Untouched'
}
But a PUT (update) on the above item using this:
{
id: hwad0912he109sj(whatever),
first_status: 'Recalled'
}
Should throw an error like: Invalid first_status
Could someone please give me an example of how this would work. I would assume you would need to use something like progressSchema.pre('save'...
Mongoose has an enum property for this usecase. See the documentation and example below:
const progressSchema = mongoose.Schema({
possible_statuses: {
type: Array
},
first_status: {
type: String,
enum: ['Untouched', 'In Progress', 'Complete']
}
});
I am creating a schema with the following code;
var Repository = require('./base/Repository');
var Connection = require('./base/Connection');
var scm = Repository.schema({
userId : String,
text: String,
date: Number });
scm.index({date:1}); scm.index({userId:1});
var repo = Repository.create('Feedback', scm, Connection);
module.exports = new repo();
But I want to give default values for the fields while creating this schema. For example I want something like that ;
var scm = Repository.schema({
userId : 12334455,
text: hello world,
date: 19.04.2018 });
How can I manage this with Mongoose ?
You can always specify default values while defining your schema. Like
Repository.schema({
userId : { type: String, default: '12334455' },
text: { type: String, default: 'Xyx' },
date: { type: String, default: 12334455 }
})
Here is documentation
Try this:
http://mongoosejs.com/docs/defaults.html
you may wish to use the setDefaultsOnInsert option.
I am struggling to insert a document inside another document. I've looked at all the entries like this but they aren't quite what I am looking for.
Here is the scenario:
I have a common document that has its own schema. Lets call it a related record:
(function(){
'use strict';
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var relatedRecordSchema = new Schema({
params: {
recordId: Schema.Types.ObjectId,
recordType: String,
recordTitle: String
},
metadata: {
dateCreated: {type: Date, default: Date.now}
}
},{ _id : false });
mongoose.model('RelatedRecord', relatedRecordSchema);
})();
I have no trouble inserting this in an ARRAY inside document that require it. I.e its configured this way:
//Embedded
relationships: {
following: [mongoose.model('RelatedRecord').schema],
followers: [mongoose.model('RelatedRecord').schema],
blocked: [mongoose.model('RelatedRecord').schema]
}
This works perfectly.
The scenario that does not work is where there is a single related record, lets say the source of a notification:
var notificationSchema = new Schema({
params: {
title: String,
imageUrl: String,
source: mongoose.model('RelatedRecord').schema
},
metadata: {
dateCreated: { type: Date, default: Date.now },
dateViewed: Date
}
});
So when I am creating the notification I try and assign the previously prepared RelatedRecord
returnObj.params.source = relatedRecord;
The record appears during a debug to be inserted (it is inside a _docs branch but far deeper than I would expect) but when the object is saved (returnObj.save()) the save routine is abandoned without error, meaning it does not enter into the callback at all.
So it looks to me that i'm confusing mongoose as the dot assignment is forcing the subdoc into the wrong location.
So the question is simple:
How do I set that subdocument?
What the question isn't:
No I don't want to populate or advice on how you would solve this problem differently. We have sensible reasons for doing things how we are doing them.
Cheers
b
As Hiren S correctly pointed out:
1) Sub-Docs = array, always. Its in the first line in the docs :|
2) By setting the type to mixed, assignment of the object worked.
I'm a dumdum.
So, I've got this schema:
var imageSchema = new Schema( {
caption: {type: String, required: true},
url: {type: String, required: true}
});
var EventSchema = new Schema({
name: {type: String, required: true},
date: {type: Date, required: true},
time: {type: String, required: true},
location: {type: String, required: true},
description: { type: String, required: false },
image: {type: String, required: false},
images: [imageSchema]
});
Requests are handled via locomotive.js, and the controller action for creating new records looks like this:
EventController.create = function() {
if(preScreen.screen.bind(this)("event", "create")) {
this.elements = modelHelper.loadValues.bind(this)();
this.saveMessage = "Save";
this.strings = strings;
if(this.req.method && this.req.method == "POST")
{
this._createEvent();
} else {
this.render();
}
} else {
this.redirect(this.urlFor({controller: "dashboard", action: "error"}));
}
};
This is a fairly standard action controller; mostly invoking an input view or or handling the _create when the received with a POST header.
the _createEvent function looks like this:
EventController._createEvent = function() {
if(!(this.elements)) this.elements = require('../templates/Event/elements')();
if(!(this.event)) this.event = new Event();
modelHelper.populate.bind(this)(this.elements, "event", function() {
modelHelper.save.bind(this)("event", this._confirm.bind(this), "create");
}.bind(this));
};
For my models I encapsulate all of the inputs in a template pattern. Rather than spend a lot of time on the framework around this (which I am working on releasing open source once I have finished doing small tweaks too) I will say that effectively the template contains one element for each path in the schema and provides some client-side details (error messages, labels etc.) these template objects are used by a modelHelper object which is fairly agnostic. Effectively what modelHelper.populate does is inspect the "type" property of each object within elements, and calls a handler for the appropriate input type.
the handler for date types is:
case "date" :
this[record][field.name] = strings.exists(this.param(field)) ?
strings.trim(this.param(field.name)) : null;
break;
although I've also tried strings.trim(Date.parse(this.param(field.name)) to get the UTC Timestamp from the user string.
I've been able to validate that the user entered date string does return a valid UTC stamp by using console.log within the date parser.
When the modelHelper.save() call is made it runs through these template objects, creates an associate array with the values picked up from the parsers and passes it to Record.save().
Most of this has been thoroughly tested and is being used in production however this is my first scenario where I am using dates other than date.now() as a default value.
What is the correct body for the date parser in order for mongodb/ the mongoose driver to push a date into a Date type?
Any string that JavaScript's Date.parse method can parse will work as the string is cast to a Date by Mongoose using this function which calls the Date constructor which uses Date.parse to parse strings.
I'm trying to perform validation without saving. The API documentation shows that there's a validate method, but it doesn't seem to be working for me.
Here's my schema file:
var mongoose = require("mongoose");
var schema = new mongoose.Schema({
mainHeading: {
type: Boolean,
required: true,
default: false
},
content: {
type: String,
required: true,
default: "This is the heading"
}
});
var moduleheading = mongoose.model('moduleheading', schema);
module.exports = {
moduleheading: moduleheading
}
..and then in my controller:
var moduleheading = require("../models/modules/heading").moduleheading; //load the heading module model
var ModuleHeadingo = new moduleheading({
mainHeadin: true,
conten: "This appears to have validated.."
});
ModuleHeadingo.validate(function(err){
if(err) {
console.log(err);
}
else {
console.log('module heading validation passed');
}
});
You may notice that the parameters I'm passing in are called 'mainHeadin' and 'conten' instead of 'mainHeading' and 'content'. However, even when I do the call to validate() it never returns an error.
I'm obviously using validate incorrectly - any tips? The mongoose documentation is really lacking!
Thanks in advance.
Your validation will never fail because you've created default attributes for both mainHeading and content in your schema. In other words, if you don't set either of those properties, Mongoose will default them to false and "This is the heading" respectively - i.e. they will always be defined.
Once you remove the default property, you'll find that Document#validate will work as you initially expected. Try the following for your schema:
var schema = new mongoose.Schema({
mainHeading: {
type: Boolean,
required: true
},
content: {
type: String,
required: true
}
});