Get fields set to unique in schema from Mongoose - node.js

I have a desire to check which fields in a schema are set to unique, similar to getting the indexes for a schema via MyCollection.collection.getIndexes(). Can this information be found somewhere on the schema object?

Try this:
var schema = new mongoose.Schema({
a: {
type: String,
unique: true
},
b: {
type: String
}
});
schema.tree.a.unique; // true
schema.tree.b.unique; // undefined
schema.path('a').options.unique; // true
schema.path('b').options.unique; // undefined

Related

Cannot Query sub sub documents

I can't access sub sub documents I want to query the sub documents implement back end pagination so that I can render them in a separate page
I've tried using dot notation something.something.something and even using this ["something"]["something"]["something"] arrays since I recently found out objects are kind of arrays
This is the model Schema || the child Schema
const modelSchema = new mongoose.Schema({
modelname: {
type: String,
required: true,
minlength: 5,
maxlength: 250
}
});
This is the Bikes Schema || parent Schema
const bikeSchema = new mongoose.Schema({
make: {
type: makeSchema,
required: true
}
})
This is how data is stored in Mongodb
"_id" : ObjectId("5d5e13e8edcbbf038c1f9b8e"),
"make" : {
"_id" : ObjectId("5d40f0b40268d80ac8c30973"),
"makename" : "{ _id: 5d40f0b40268d80ac8c30973, makename: 'ducatii', __v: 0 }"
}
The expected output according to the documentation in order to query the makename ducatii is to do something like this
console.log(bikes[0]["make"]["makename"]["makename"])
or this
console.log(bikes[0].make.makename.makename)
To embedded document into a document you have to do this like the below
var childSchema = new Schema({ name: 'string' });
var parentSchema = new Schema({
// Array of subdocuments
children: [childSchema],
// Single nested subdocuments. Caveat: single nested subdocs only work
// in mongoose >= 4.2.0
child: childSchema
});
Your case
const modelSchema = new mongoose.Schema({
makename: {
type: String,
required: true,
minlength: 5,
maxlength: 250
}
});
const bikeSchema = new mongoose.Schema({
make: {
makename: modelSchema
}
})
then you can access it like
console.log(bikes[0]["make"]["makename"]["makename"])
Two things to note:
If the returned result is a MongoDB cursor object, then you can't access via an array index. You'll need to retrieve the item from the cursor using the appropriate method.
Your first makename field points to a JSON string, not an object. You cannot access the nested makename.makename from a JSON string. You must first decode the JSON into an object before accessing the nested property.
This seems to be an issue with how you are storing your sub documents.
For example:
bikes[0].make.makename is actually a string, not a valid object. You won't be able to JSON.parse this string either, because you would have to wrap each key/value with escaped double quotes.
If you are able to store this sub-document correctly, then you should be good to use the object in the way you expect!

default value for ref collection in mongoose

I have a user profile, I have a field of 'earning' and it look like this in the schema
earning: {
type: Schema.Types.ObjectId,
ref: 'Earning'
}
This how do I make a default value for earning field when a new user is created? I can't do this
earning: {
type: Schema.Types.ObjectId,
ref: 'Earning',
default: 0
}
I got error of
Cast to ObjectId failed for value "0" at path "earning"
What you are doing wrong here is trying to cast a number on an ID field. Since it's a reference of another object Id field, you can not set 0 to it. What you need to do is to set null when a user is created in db and initialize it with a null value of earning.
Like:
earning: {
type: Schema.Types.ObjectId,
ref: 'Earning',
default: null
}
When instantiating a document based on a Schema which has a key of type 'ObjectId' and a ref to another collection, the only way that I've found to set a 'default' value is through the use of Mongoose middleware at the schema level as described here. For example, setting a comment's author to a default 'guest' document from a User collection when the author is not logged in might look like this:
// user document in MongoDB
{
_id: ObjectId('9182470ab9va89'),
name: 'guest'
}
// CommentSchema
const mongoose = require('mongoose')
const CommentSchema = mongoose.Schema({
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
},
body: String
})
CommentSchema.pre('save', function (next) {
this.author == null ? this.author = '9182470ab9va89' : null
next()
})
module.exports = mongoose.model('Comment', CommentSchema)
This example uses the 'save' pre hook with the ObjectId hardcoded in the schema for demonstration purposes, but you can replace the hardcoding of the ObjectId with a call to your backend or however else you'd like to get that value in there.
As I understand earning is indication of how much user earn so it should be of type Number not ObjectId
so try to change your Schema to be
earning: {
type: Number,
ref: 'Earning',
default: 0
}
so you can use 0
Note: if you should use ObjectId for some reason so the answer of 'Haroon Khan' is the correct answer.

How can I make a mongo document filed read-only in mongoose schema field declaration? [duplicate]

Short and clear: is there any way to prevent setting a schema field but allowing to get the value?
I've been around the Mongoose Documentation but can't find what I'm looking for.
An alternative if you want to set a default value that can never be changed:
var schema = new Schema({
securedField: {
type: String,
default: 'Forever',
set: function (val) { return this.securedField; }
});
Define the field as a virtual getter instead of a traditional field.
For example, say you wanted to make the pop field of your collection read-only when accessed via Mongoose:
var schema = new Schema({
city: String,
state: String
});
schema.virtual('pop').get(function() {
return this._doc.pop;
});
By accessing the private _doc member of your model instance it's possible this may break in the future, but this worked fine when I tested it just now.
Since mongoose 5.6 you can do: immutable: true
var schema = new Schema({
securedField: {
type: String,
default: 'Forever',
immutable: true
}
});
You can just return from set the same value as the default value, no need to reference the _this document:
var schema = new Schema({
securedField: {
type: String,
default: 'Forever',
set: () => 'Forever'
});

When using mongoose, how can I imply required validation only to the field inside the object where the object itself can be null?

here is my simple schema for my model
var schema = new mongoose.Schema({
User: {{
Name:{ type: String, required: true }
}
},
Amount: { type: Number, required: true }
})
var model = cnn.model("test", schema);
var first = new model({Amount:12});
What I am expecting is that the'required option only apply if I create an object with User. When I create a object without User, I don't need to check.
That is if the path is without User, it should have also User.Name, if it doesn't, it's also ok
But the way I set up the schema seems failed when I try to store the object without User and it says that: Path User.Name is required.
So is there anyway in monoose library that can realize my intention?

Storing a copy of a document embedded in another document in MongoDB via Mongoose

We have a requirement to store a copy of a Mongo document, as an embedded subdocument in another document. It should have a reference to the original document. The copied document needs to be a deep copy, like a snapshot of the original.
The original document's schema (defined with Mongoose) is not fixed -
it currently uses a type of inheritance to allow different additions to the Schema depending on "type".
Is there a way to such a flexible embedded schema within a Mongoose model?
Is it something that needs to be injected at runtime, when we can know
the schema?
The models / schemas we have currently look like this:
///UserList Schema: - this should contain a deep copy of a List
user: {
type: ObjectId,
ref: 'User'
},
list: {
/* Not sure if this is a how we should store the reference
type: ObjectId,
ref: 'List'
*/
listId: ObjectId,
name: {
type: String,
required: true
},
items: [{
type: ObjectId,
ref: 'Item'
}]
}
///List Schema:
name: {
type: String,
required: true
},
items: [{
type: ObjectId,
ref: 'Item'
}],
createdBy: {
type: ObjectId,
ref: 'User'
}
The code we currently have uses inheritance to allow different item types. I realise this technique may not be the best way to achieve the flexibility we require and is not the focus of my question.
///Item Model + Schema
var mongoose = require('mongoose'),
nodeutils = require('util'),
Schema = mongoose.Schema,
ObjectId = Schema.Types.ObjectId;
function ItemSchema() {
var self = this;
Schema.apply(this, arguments);
self.add({
question: {
type: String,
required: true
}
});
self.methods.toDiscriminator = function(type) {
var Item = mongoose.model('Item');
this.__proto__ = new Item.discriminators[type](this);
return this;
};
}
nodeutils.inherits(ItemSchema, Schema);
module.exports = ItemSchema;
I think you just need to create an empty {} object for the document in your parent mongoose schema. This way you´ll be able to store any object with a hardcopy of all it´s data.
parentobj : {
name: Sring,
nestedObj: {}
}
I think at this point, what you´ll need is to mark your nested objet as modified before you save it. Here is an example of my mongoose code.
exports.update = function(req, res) {
User.findById(req.params.id, function (err, eluser) {
if (err) { return handleError(res, err); }
if(!eluser) { return res.send(404); }
var updated = _.merge(eluser, req.body);
//This makes NESTEDDATA OBJECT to be saved
updated.markModified('nestedData');
updated.save(function (err) {
if (err) { return handleError(res, err); }
return res.json(200, eluser);
});
});
};
In addition, if you need an array of different documents in nestedDocument, the right way is this one:
parentobj : {
name: Sring,
nestedObjs: [Schema.Types.Mixed]
}
Please check Mongoose Schema Types carefully
EDIT
As you said, I´ll add you final solution as including ItemSchema in the nestedObj array definition to clarifythe type of the object to a determined one..
var ItemSchema = new Schema({
item1: String,
item2: String
});
var parentobj = new Schema({
name: Sring,
nestedObj: [ItemSchema]
});
EDIT 2:
Remember adding new Items to the nestedArray, must be done with nestedArray.push(item)
regards!!

Resources