Can't get defaultsTo to work with waterline/sailsjs - javascript

I'm trying to set a default value to a field when I create a new item in the database, but I can't make it to work.
I am using SailsJS 0.12.1 currently, which is the latest version
This is how my file looks like:
models/Users.js
module.exports = {
schema: true,
attributes: {
firstName: {
type: 'string',
required: true,
},
role: {
type: 'string',
enum: ['admin', 'user', 'limited', 'suspended', 'deleted'],
defaultsTo: 'limited'
},
}
}
When the element is created in the database, I don't get the role value. It looks like that:
{
"_id": {
"$oid": "56f8616163a59cf813998f8a"
},
"firstName": "Alex",
"createdAt": {
"$date": "2016-03-27T22:40:33.151Z"
},
"updatedAt": {
"$date": "2016-03-27T22:40:33.151Z"
}
}
Any idea what I forgot?
Thanks!

I had a similar issue earlier today. I was able to resolve this by adding required is 'true'.
Example of New User Model:
module.exports = {
schema: true,
attributes: {
firstName: {
type: 'string',
required: true,
},
role: {
type: 'string',
required: true,
enum: ['admin', 'user', 'limited', 'suspended', 'deleted'],
defaultsTo: 'limited'
},
}
}
I hope this helps.

Related

How Save Nested Array into Mongodb Using Mongoose schema?

Actually, Only allFacilities field makes an error in Schema, Please Someone help by making sure the correct format of the mongoose schema allFacilities field for allFacilities array data
Actually, Only allFacilities field makes an error in Schema, Please Someone help by making sure the correct format of the mongoose schema allFacilities field for allFacilities array data
My data Look Like That
{
"name": "This is Name countru",
"type": "Hotel",
"country": "Bangladesh",
"city": "Chittagong",
"address": "22 D Block, Kolpolok Residense, Bakulia,",
"distance": "Chittagong",
"title": "tis is best hotel",
"desc": "Pamper yourself with a visit to the spa, which offers massages, body treatments, and facials. You can take advantage of recreational amenities such as an outdoor pool, a spa tub, and a sauna. Additional features at this hotel include complimentary wireless Internet access, concierge services, and a banquet hall. Grab a bite at The Exchange, one of the hotel's 3 restaurants, or stay in and take advantage of the 24-hour room service. Relax with your favorite drink at the bar/lounge or the poolside bar. Featured amenities include a business center, dry cleaning/laundry services, and a 24-hour front desk. Free valet parking is available onsite. Make yourself at home in one of the 241 air-conditioned rooms featuring LED televisions. Complimentary wireless Internet access keeps you connected, and satellite programming is available for your entertainment. Private bathrooms with separate bathtubs and showers feature hair dryers and slippers. Conveniences include phones, as well as safes and coffee/tea makers. Distances a",
"cheapestPrice": "105",
"rooms": [
"629dd3bae549560b971612da",
"629dd418e549560b971612df",
"629dd481e549560b971612ea",
"629dd4b3e549560b971612f0",
"629dd4b4e549560b971612f6",
"629dec61e549560b9716139f"
],
"photos": [
"http://res.cloudinary.com/cloudmonzu/image/upload/v1655222493/upload/jxsbi7r26cyqgnwg65ni.jpg",
"http://res.cloudinary.com/cloudmonzu/image/upload/v1655222494/upload/bybbcdb8iluy0t7smf1u.jpg",
"http://res.cloudinary.com/cloudmonzu/image/upload/v1655222493/upload/pzfzk3umv5agumt30ygo.jpg"
],
"allFacilities": [
{
"hotelfacilities": [
"dsds",
" sdsd",
" sdd"
]
},
{
"roomfacilities": [
"sdsd",
" dss",
" dss"
]
},
{
"wellnessSpa": [
"sds",
" dsd",
" sdsd",
" sds"
]
}
]
}
My Mongoose Schema Look Like That
import mongoose from "mongoose";
const HotelSchema = new mongoose.Schema({
name: {
type: String,
required: true,
},
type: {
type: String,
required: true,
},
country: {
type: String,
required: true,
},
city: {
type: String,
required: true,
},
address: {
type: String,
required: true,
},
distance: {
type: String,
required: true,
},
title: {
type: String,
required: true,
},
desc: {
type: String,
required: true,
},
cheapestPrice: {
type: Number,
required: true,
},
rooms: {
type: [String],
},
photos: {
type: [String],
},
allFacilities: {
type: [String],
required: true,
},
rating: {
type: Number,
min: 0,
max: 5,
},
featured: {
type: Boolean,
default: false,
},
});
export default mongoose.model("Hotel", HotelSchema)
use "type: Array" for rooms, photos and allFacilities
name: {
type: String,
required: true,
},
type: {
type: String,
required: true,
},
country: {
type: String,
required: true,
},
city: {
type: String,
required: true,
},
address: {
type: String,
required: true,
},
distance: {
type: String,
required: true,
},
title: {
type: String,
required: true,
},
desc: {
type: String,
required: true,
},
cheapestPrice: {
type: Number,
required: true,
},
rooms: {
type: Array,
},
photos: {
type: Array,
},
allFacilities: {
type: Array,
required: true,
},
rating: {
type: Number,
min: 0,
max: 5,
},
featured: {
type: Boolean,
default: false,
},
});

How to use mongoose transactions with updateMany?

I am using the mongoose updateMany() method and I also want to keep it a part of transaction. The documentation shows the example of save() where I can do something like Model.save({session: mySession}) but don't really know how to use it with for example Model.updateMany()
UPDATE:
For example I have two models called SubDomain and Service and they look like this respectively:
SUB-DOMAIN
{
name: {
type: String,
required: true,
},
url: {
type: String,
required: true,
unique: true,
},
services: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "Service",
},
],
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
}
SERVICE:
{
name: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
price: { type: Number },
tags: { type: Array },
packages: [
{
name: { type: String, required: true },
description: { type: String, required: true },
price: { type: Number, required: true },
},
],
map: { type: String },
isHidden: {
type: Boolean,
required: true,
default: false,
},
sortingOrder: { type: Number },
isForDomain: { type: Boolean, required: false, default: false },
isForSubDomain: { type: Boolean, required: false, default: false },
subDomains: [
{
type: mongoose.Schema.Types.ObjectId,
ref: "SubDomain",
},
],
}
Now the main field here is the services field in SubDomain and subDomains field in Service.
The complicated part😅:
Whenever the user wants to create new service, I want to $push that service's _id into the array of services of all the subDomains inside that new service
And for that, I am using the updateMany() like this:
const sess = await mongoose.startSession();
sess.startTransaction();
const newService = new Service({
_id: mongoose.Types.ObjectId(),
subDomains: req.body.subDomains
...foo
})
await SubDomain.updateMany(
{ _id: { $in: req.body.subDomains } },
{ $push: { services: newService._id } }
);
The problem starts here, of course I can do:
newService.save({session: sess})
but how do I keep my SubDomain's updateMany in the same transaction (i.e sess)
I know my example is difficult to wrap your head around but I have tried to pick a simplest example rather than copying the exact same code which would have been a lot more difficult

Mongoose/Mongodb: Index Already Exists With Different Options

I am using Mongoose 5.1.7 and attempting to create a compound index across multiple text indexes in my defined schema. Here is my schema definition:
const mongoose = require('mongoose');
const alumniSchema = mongoose.Schema({
firstName: {
type: [String],
required: true
},
lastName: {
type: [String],
required: true
},
classYear: {
type: Number,
required: true
},
photoURL: {
type: String,
},
education: [
{
school: {
type: String,
required: true
},
gradYear: {
type: Number,
required: true
},
degreeType: String,
degreeSubject: String,
}
],
jobs: [
{
employer: {
type: String,
required: true
},
position: String,
startDate: Date,
endDate: Date,
isCurrent: Boolean
}
],
contactInfo: {
phoneNumber: {
type: String,
},
email: {
type: String,
}
},
})
alumniSchema.index({ firstName: 'text', lastName : 'text', email: 'text' });
module.exports = mongoose.model('Alumni', alumniSchema);
When I boot up the server, I receive the following error:
MongoError: Index: { v: 2, key: { _fts: "text", _ftsx: 1 }, name: "firstName_text_lastName_text_email_text", ns: "5b3be578c0c6e317f7c1bc2b_test.alumnis", background: true, weights: { email: 1, firstName: 1, lastName: 1 }, default_language: "english", language_override: "language", textIndexVersion: 3 } already exists with different options: { v: 2, key: { _fts: "text", _ftsx: 1 }, name: "firstName_text_lastName_text_classYear_text_education.school_text", background: true, weights: { classYear: 1, education.school: 1, firstName: 1, lastName: 1 }, default_language: "english", language_override: "language", ns: "5b3be578c0c6e317f7c1bc2b_test.alumnis", textIndexVersion: 3 }
I have been messing around with this for a while and evidently previously created an index. When I use the mongo shell to check the indexes that I currently have set up, however, I cannot find the index "firstName_text_lastName_text_classYear_text_education.school_text" referenced by the error message:
> db
test
> db.collection.getIndexes()
[ ]
I am at an impasse--I'm not sure if I've incorrectly created the index, or if I am supposed to drop the index (it doesn't look like Mongoose natively supports a dropIndex() function).
Has anyone else dealt with this issue? Thanks!
Looks like Mongoose dynamically creates the index at runtime. The trick for me was adding:
var Alumni = mongoose.model('Alumni', alumniSchema);
Alumni.collection.dropIndex('firstName_text_lastName_text_classYear_text_education.school_text', function(err, result) {
if (err) {
console.log('Error dropping index!', err);
}
});
and then restarting the server.
THEN I was able to change the index to whatever I wanted. Note that I still needed to add the above code segment and restart the server every time I wanted to update the index.

Mongoose, enforce changes to schema after mongoose.model('core_user').schema = new mongoose.schema(...)

I am using the Express-Restify-Mongoose library to generate all of my endpoints for a REST api.
I am storing my schemas in a collection named 'core_schema.' Each time the server starts all records within that collection are grabbed using a find() method. This provides an array of all available collections with defined schemas.
db.on('open', function(){
findDocs('core_schema', {}, function(docs){
var tempString = JSON.stringify(docs);
var tempObj = JSON.parse(tempString);
for (var i = 0; i < tempObj.length; i++) {
var temp_schema = new mongoose.Schema(tempObj[i].schema_data, { collection: tempObj[i].collection_name });
var temp_model = mongoose.model(tempObj[i].collection_name, temp_schema);
restify.serve(router, temp_model, { plural: false, name: tempObj[i].collection_name, preCreate: setDateTimes });
}
});
});
I would like to be able to make changes to the schema to enforce new POST rules, but when I try to use a test example like:
mongoose.model('core_user').schema = new mongoose.Schema({
update_count: { type: "String", required: false },
created_date: { type: "String", required: false },
created_by: { type: "String", required: false },
updated_date: { type: "String", required: false },
updated_by: { type: "String", required: false },
first_name: { type: "String", required: true },
last_name: { type: "String", required: true },
username: { type: "String", required: true },
password: { type: "String", required: true },
somethingElse: { type: "String", required: true }
}, {collection: 'core_user'})
Where 'somethingElse' is the new field I am trying to enforce it does not enforce it. What am I doing wrong? Is there no way to update the model to use the new schema?
To update a Mongoose schema, you'll need to use the Schema.add method. You can update the schema for a model using the code below:
mongoose.model('core_user').schema.add({ somethingElse: {
type: 'String',
required: true
}});

Upsert: Unable to invalidate a subdocument that has not been added to an array

I have an upsert query in mongoose which was working in 3.8 but, after I've upgraded to 4 I'm getting
Unable to invalidate a subdocument that has not been added to an array
this is my model:
var ActivitySchema = new Schema({
owner:{
type: Schema.Types.ObjectId,
ref: 'User'
},
sequence:{
type:Number,
default: 0
},
items:[
{
posted:{
type:Date,
default:Date.now
},
verb:{
type: String,
enum: [ 'leave','join','support','share','comment', 'upload', 'rate','message','update', 'signup']
},
text:{
type: String,
},
reference: {
objectType:{
type: String,
enum: [ 'document','element','process', 'project', 'user']
},
refObj:{}
}
}]
});
the upsert:
Activity.update({
$and:[
{'owner':ownerId},
{'sequence':bucket}
]},
{
$push:{items:newItem }
},
{
upsert:true
}).execAsync();
and the data is like this:
//newItem
{ verb: 'join',
text: 'Has joined to a team',
reference:
{
refObj: { teamId: '56269fd1e923cc7a7b46dcf8', name: 'test1' },
objectType: 'user'
}
}
ownerId is a mongoId like 56251c01507dc35423694118
and bucket is an integer 0
is there any breacking change that I need to be aware?, I've been looking and I haven't found yet related, any other workaround, solution?
I had encountered the same problem, if it is the same case then make sure all fields type are matched to the mongoose.model('yourModel').
Hopes that helps.

Categories