How to post a date object in nodejs and mongodb - mongodb

Following is my schema definition:
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var StudentSchema = new Schema({
name: String,
family: String,
created: {
type: Date,
default: Date.now}
});
module.exports = mongoose.model('Student', StudentSchema);
How do I have post it? because whatever value I post, it default value, that current time. I tried following two things:
{
"name": "abc",
"family": "xyz",
"created": "2016-12-12"
}
{
"name": "abc",
"family": "xyz",
"created": "1467883104"
}
In both the cases, it stored current time only. Not the one which I am passing.

Your schema defines the field created as Date object. What you are trying to store, however, is a plain string. You have to pass a real Date object instead:
{
name: "abc",
family: "xyz",
created: new Date("2016-12-12")
}

Related

Documents inserted without schema not being found with schema

I have two new collections in MongoDB of data that I pulled from an old Firestore database that I'm moving to mongo. Since the total number between these two collections is roughly 20,000, I opted to paste the raw JSON into the insert document section in mongo, which worked like a charm and I didn't have to write a new insert route to do the same.
I then created a schema in Mongoose that matched the inserted documents, and tried to use the schema to pull back some data, and its always returning nothing.
An example of a ticket inserted via JSON:
{
"title": "How to add and manage users for your company in QuickBooks Online",
"priority": "1",
"type": "Video",
"course": "G205",
"transcriptId": "07dom27Zz98jakvB1oh5",
"status": "In Review",
"tags": "",
"url": "",
"revisionNumber": 0,
"directoryId": 19,
"checkedOut": false
},
And my schema I made to match. The collection name in mongo is also called oldTickets, the plural of my schema name here:
const mongoose = require('mongoose');
var Schema = mongoose.Schema
const schema = new Schema({
course: { type: String },
title: { type: String },
priority: { type: String },
type: { type: String },
course: { type: String },
transcriptId: { type: String },
status: { type: String },
tags: { type: String },
url: { type: String },
revisionNumber: { type: Number },
directoryId: { type: Number },
checkedOut: { type: Boolean },
});
module.exports = mongoose.model('oldTicket', schema);
And finally my model import and fetch call:
const OldTicket = require('./models/model_old_ticket');
/***************************************************************************
* Get Old Tickets - Returns all old tickets, 10 at a time
****************************************************************************/
app.get('/getOldTickets/:offset', (req, res) => {
checkConnection();
OldTicket.find().skip(parseInt(req.params.offset)).limit(10).exec((err, data) => {
if (err){ res.status(500).send({err: err}); }
//If we got data, count the tickets & return the tickets & count
if (data) {
OldTicket.find().countDocuments().then(count => {
return res.status(200).send({
tickets: data,
count: count
})
})
}
});
});
Why isn't this finding anything? Both the count and the tickets are 0. I've run into this issue before when manually creating a collection without a schema, and in those instances I would simply delete the collection, write a route to create a document, and then things would work fine. But with the large data size of these two collections, I'd rather not do that since everything should be working as is.
Edit: Example of document in Mongo
And the name of the collection I'm currently viewing:
And I just now realized that for some reason there are now two collection names, oldTickets, which has data, and oldtickets, which is empty. I'm assuming my query is searching through the empty one? How can I get it to go to the one that actually has data?
can you attach the screenshot of your data with the collection? might be it's different.in mongoose, every collection name is complete with 's'. please verify your collection is created manually by you then it has to same as mongoose schema and also completed with 's'.
example:
const mongoose = require("mongoose");
const schema = new mongoose.Schema(
{
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
index: true
},
filmId: {
type: mongoose.Schema.Types.ObjectId,
index: true
},
filmType: {
type: String,
index: true
},
birthday: {
type: Date
},
age: {
type: Number
},
terms: {
type: Boolean
}
},
{
versionKey: false,
timestamps: true,
}
);
schema.index({ filmId: 1, user: 1 })
module.exports = mongoose.model("UserAgeVerification", schema);
see my database

GraphQL and MongoDB - "Cast to Array failed" With Array [duplicate]

I am trying to create the model for my mongodb database using mongoose. This is what I am trying to do:
var Class = mongoose.model('Class', {className: String, marks: [{type: Number}], grades: [{type: Number}]});
var User = mongoose.model('User', {email: String, classes: [Class] });
//Lets create a new user
var class1 = new Class({className: 'aaa', marks: [72, 88, 63], grades: [30, 40, 30]});
var user1 = new User({email: 'aaa#some.com', classes: [class1]});
Saving class1 seems to work okay but when I check mongodb, this is displayed:
{
"_id" : ObjectId("someId"),
"className" : "TEST1234",
"grades" : [ 30, 40, 30 ],
"marks" : [ 72, 88, 63 ],
"__v" : 0
}
What is "__v : 0"?
Saving the user is not successful at all, this is the following error:
ValidationError: CastError: Cast to Array failed for value "{ marks: [ 72, 88, 63 ],
grades: [ 30, 40, 30 ],
_id: someId,
className: 'TEST1234' }" at path "classes"
`
What exactly does the error mean? Why is it casting anything to a array? Shouldn't classes: [Class] be an array of type class?
Man, I had a similar issue creating an Schema like this:
QuestionnaireSchema = mongoose.Schema({
formId: Number,
name: String,
questions: [
{
type: String,
title: String,
alternatives:[{
label: String,
value: "Mixed"
}]
}
]
});
My mistake was that I am using "type" as a field name and this is reserved word in mongoose.
I just change:
type: String,
to
formType: String,
and that works.
see: https://github.com/Automattic/mongoose/issues/1760
Explicitly defining the type rule on a property called type is allowed and won't throw an error. like this:
type: {type: String}
Try changing the class definition to :
var classSchema = mongoose.Schema({className: String, marks: [{type: Number}], grades: [{type: Number}]});
var userSchema = mongoose.Schema({email: String, classes: [classSchema] });
var User = mongoose.model('User',userSchema);
This is required since mongoose is not able to parse the object without a related schema. Now when you create a new Schema for the internal class object and refer it in the main userSchema mongoose should be able to parse your object.
Your model definition is incorrect, you should fix like below.
// var Schema = mongoose.Schema;
var User = mongoose.model('User',{
email: String,
classes: [ {type: Schema.Types.ObjectID, ref: 'Class'}]
});
var Class1 = new Class({/*yourDataWillBeHere*/})
Class1.save(function(err, classData) {
var User1 = new User({/*YourDataWillBeHere*/})
User1.classes.push(classData._id);
User1.save(function(err, userData) {
//make something with userData object
})
})
Then you can get fetched data using with populate() like this
User
.find()
.populate('classes')
.exec()
By default, if you have an object with key 'type' in your schema, mongoose will interpret it as a type declaration.
// Mongoose interprets this as 'loc is a String'
var schema = new Schema({ loc: { type: String, coordinates: [Number] } });
Changing the typeKey:
var schema = new Schema({
// Mongoose interpets this as 'loc is an object with 2 keys, type and coordinates'
loc: { type: String, coordinates: [Number] },
// Mongoose interprets this as 'name is a String'
name: { $type: String }
}, { typeKey: '$type' }); // A '$type' key means this object is a type declaration
Link: http://mongoosejs.com/docs/guide.html#typeKey
Just for Update
Now Mongoose supports subdocuments, which are the documented way to nest arrays,
var arraySchema = new Schema({
property: String
});
var objectSchema = new Schema({
arrays: [arraySchema]
});
Sources
http://mongoosejs.com/docs/schematypes.html
I got a similar issue using mongoose 5.7.0+ using double nested schema.
Except it wasn't related to the keyword type but a mongoose validation bug.
https://github.com/Automattic/mongoose/issues/8472
Temporary workaround: Use Schema.Types.Mixed for the subschema

Mongoose query not showing subdocument

I can't get mongoose to show subdocument when running find() while it displays perfectly well in mongodb shell.
Subdocument should be embedded based on my schema, not objectId referenced, so I shouldn't be running any black magic voodoo to get my data to show up.
const UserSchema = new mongoose.Schema({
username: String;
xp: Number;
//etc.
});
const RoomSchema = new mongoose.Schema({
timestamp: { type: Date, default: Date.now },
status: { type: String, enum: ["pending", "ongoing", "completed"]},
players: {
type: [{
points: { type: Number, default: 0 },
position: String,
user: UserSchema
}],
maxlength:2
}
});
After adding a new room with:
let room = new Room(coreObj);
room.players.push({
points: 0,
position: 'blue',
user: userObj //where userObj is a result of running findById on User model
});
It displays nicely in mongo shell, when running db.rooms.find({}).pretty() I can see that full document has been added. However, when running on mongoose model:
Room.find({}).exec((err,rooms)=>{
console.log(rooms[0].toJSON());
});
I don't see user subdocument, moreover I cannot see user field entirely! What seems to be the problem?
logged json from mongoose model:
{
"status": "pending",
"_id": "5cf5a25c050db208641a2076",
"timestamp": "2019-06-03T22:42:36.946Z",
"players": [
{
"points": 0,
"_id": "5cf5a25c050db208641a2077",
"position": "blue"
}
],
"__v": 0
}
json from mongo shell:
{
"_id" : ObjectId("5cf5a25c050db208641a2076"),
"status" : "pending",
"timestamp" : ISODate("2019-06-03T22:42:36.946Z"),
"players" : [
{
"points" : 0,
"_id" : ObjectId("5cf5a25c050db208641a2077"),
"position" : "blue",
"user" : {
"xp" : 0,
"_id" : ObjectId("5cf2da91a45db837b8061270"),
"username" : "bogdan_zvonko",
"__v" : 0
}
}
],
"__v" : 0
}
Keeping best practice in mind, I think it would be more appropriate to reference the UserSchema in the RoomSchema. Something like:
...
user: {
type: Schema.Types.ObjectId,
ref: 'UserSchema'
}
Then you would store the user._id in that field.
This way, if the user is modified, your RoomSchema is always referencing the correct information. You could then get the user using Mongoose's populate
I'm not entirely sure why you can't see the sub-sub-document, but this code example printed it correctly for me. Example was originally posted in https://mongoosejs.com/docs/subdocs.html but modified slightly to contain sub-sub-document so it looks similar to your code:
var grandChildSchema = new mongoose.Schema({ name: 'string' });
var childSchema = new mongoose.Schema({ name: 'string', grandChild: grandChildSchema });
var parentSchema = new mongoose.Schema({ children: [childSchema] });
var Parent = mongoose.model('Parent', parentSchema);
var parent = new Parent({
children: [
{ name: 'Matt', grandChild: {name: 'Matt Jr'} },
{ name: 'Sarah', grandChild: {name: 'Sarah Jr'} }
]
})
parent.save(function() {
Parent.find().exec(function(err, res) {
console.log(JSON.stringify(res[0]))
mongoose.connection.close()
})
});
Executing this code resulted in:
{
"_id": "5cf7096408b1f54151ef907c",
"children": [
{
"_id": "5cf7096408b1f54151ef907f",
"name": "Matt",
"grandChild": {
"_id": "5cf7096408b1f54151ef9080",
"name": "Matt Jr"
}
},
{
"_id": "5cf7096408b1f54151ef907d",
"name": "Sarah",
"grandChild": {
"_id": "5cf7096408b1f54151ef907e",
"name": "Sarah Jr"
}
}
],
"__v": 0
}
This was tested using Mongoose 5.5.12.
Note that I was using JSON.stringify() to print the document instead of using Mongoose's toJSON().
I just met a very similar problem, i think i got it.
the whole point is in model which you use:
const RoomSchema = new mongoose.Schema({
...
players: {
type: [{
...
user: UserSchema
...
but then you make
room.players.push({
points: 0,
position: 'blue',
user: userObj //where userObj is a result of running findById on User model
});
so you are missing the "type" subfield, so your doc is not compliant with your RoomSchema and mongoose do not show the parts which does not fit schema.

Mongoose find returns empty array

I have mongoDB document which looks like this:
{
"_id": {
"$oid": "5b99247efb6fc01dae438815"
},
"participants": [
"5b758a8341ee61f049ded486",
"5b94fb4ffb6fc01dae40eae3"
]
}
The document Schema in Mongoose is defined as such
var conversationSchema = new mongoose.Schema({
participants: [{ type: mongoose.Schema.ObjectId, ref: 'User'}],
});
I am fetching the data as such
var ccc = Conversation.find({participants : "5b758a8341ee61f049ded486"});
ccc.exec(function(err, conversations){
res.status(200).json(conversations);
});
The problem is that I am getting an empty array response [].
I think the problem is with Schema but I can't figure out how can I make this to work.
EDIT,
If I change my Schema to the following it will work:
var conversationSchema = new mongoose.Schema({
participants: [{ type: String}],
});
But I want to work with mongoose.Schema.ObjectId and not Strings as foreign key.
Try adding Types to this line:
participants: [{ type: mongoose.Schema.Types.ObjectId, ref: 'User'}]
It wont recognize the items in the array because they are strings you should have instead an object like {"$oid": "585bb0086c57cd2265b1cbd3"} so reinsert the items in you db and try again.

How to set property of a model from a property of a `population` field in mongoose?

I have a Post and its author property is set to User by using ref. Suppose there is a country field in User, how to make Post schema to have a country property as well which value is from User.country after population.
const Post = new Schema({
text: String,
author: {
type: ObjectId,
ref: 'User'
},
// How to set the virtual property country which is from User.country?
});
I know there is a Populate Virtuals in Mongoose, but it seems it just another way of populating, it won't pick up one of the properties, but the whole referenced record. Or maybe I get it wrong?
I know I can refer the country from Post.author.country, but I want a Post.country as well.
How to solve this?
Could I do this at the schema level?
If you use Populate Virtuals you can do the following :
var schemaOptions = {
toObject: {
virtuals: true
},
toJSON: {
virtuals: true
}
};
var PostSchema = new Schema({
text: String,
id: false,
author: {
type: Schema.Types.ObjectId,
ref: 'User'
}
}, schemaOptions);
PostSchema.virtual('country').get(function() {
return this.author.country;
});
Using :
Post.find({}).populate('author').exec(function(error, data) {
console.log(JSON.stringify(data));
});
it gives :
[{
"_id": "59d924346be5702d16322a67",
"text": "some text",
"author": {
"_id": "59d91f1a06ecf429c8aae221",
"country": "France",
"__v": 0
},
"__v": 0,
"country": "France"
}]
Check this gist for a full example