Mongoose validation error - what is it telling me? - node.js

I'm trying to use a JSON file to populate my DB - I've had success with some other files, but this file / model is throwing validation errors and the errors aren't very helpful to me - They say there is a validation error, they even kinda tell me that it's at a forEach line in the schematype.js file - but I'm not gonna go and change a file in the node-modules folder...especially when I think it's my coding fault.
"mongoose": "4.9.8"
This is in the APP.JS - which calls /loaddata:
app.get('/api/loadData', (req, res) => {
var Xs = require( './_mock_data/x.json' );
for ( var i in Xs ) {
X.create( Xs[i] );
console.log( Xs[i] );
};
});
This is in my model page:
const XSchema = mongoose.Schema({
name:{
type: String,
required: true
},
state:{
type: String
},
type:{
type: String
},
people:{
type: [mongoose.Schema.Types.Mixed]
},
create_date:{
type: Date,
default: Date.now
}
});
My JSON file looks like this - I think the offending data is the "people" with a Mixed type - my confusion comes with the fact that it IS an array of people, so the forEach should loop it - why is it failing?
[
{
"name": "Building One",
"state": "Alaska",
"people": [{
"position": "Chair",
"department": "Sales",
"email": "aftcs#blah.io",
"phone": "",
"name": "John Smith"
}],
"type": "Business"
}, {
"name": "Fairbanks Folly",
"state": "Maine",
"people": [{
"position": "Sitting",
"department": "AAA",
"email": "ffjda#uafert.com",
"phone": "",
"name": "Jane Aspnes"
}, {
"position": "Standing",
"department": "BBB",
"email": "jmbicigo#Maine.com",
"phone": "",
"name": "James Bicigo"
}, {
"position": "Lying",
"department": "AAA",
"email": "kmbutlerhopkins#Craf.org",
"phone": "",
"name": "Kam Butler-Hopkins"
}],
"type": "Other"
}
]
And lastly - the ERROR -
Unhandled rejection ValidationError: College validation failed
at new ValidationError (C:\MyProject\node_modules\mongoose\lib\error\validation.js:23:11)
at model.Document.invalidate (C:\MyProject\node_modules\mongoose\lib\document.js:1629:32)
at C:\MyProject\node_modules\mongoose\lib\document.js:1501:17
at validate (C:\MyProject\node_modules\mongoose\lib\schematype.js:733:7)
at C:\MyProject\node_modules\mongoose\lib\schematype.js:778:11
at Array.forEach (<anonymous>)
at SchemaString.SchemaType.doValidate (C:\MyProject\node_modules\mongoose\lib\schematype.js:738:19)
at C:\MyProject\node_modules\mongoose\lib\document.js:1499:9
at _combinedTickCallback (internal/process/next_tick.js:131:7)
at process._tickCallback (internal/process/next_tick.js:180:9)
Again, any help and insight is much appreciated!

Related

How to query all documents where array field have at least one object-element with property equal 'X'?

I have some MongoDB documents like that:
{
"group": "P32666",
"order": [{
"_id": {
"$oid": "5e8e9b40e7999f6b90fd88bf"
},
"name": "Dmitriy A",
"login": "example",
"password": "example",
"email": "example",
"level": "user",
"uuid": "b6a19744-bb20-4d39-9e1e-0ca5b464f890"
}, {
"_id": {
"$oid": "5e8ea03f5a21c26b90983de4"
},
"name": "Dmitriy B",
"login": "example",
"password": "example",
"email": "example",
"level": "user",
"uuid": "556924c3-605c-44cc-8a26-d32f58222e89"
}, {
"_id": {
"$oid": "5e8ea0645a21c26b90983de5"
},
"name": "Dmitriy C",
"login": "example",
"password": "example",
"email": "example",
"level": "user",
"uuid": "aef00707-ef00-4ce9-918b-5cef17e7280b"
}]}
I'm working with Mongo in Mongoose and can't understand how to query all documents(like above) where field(array) "order" has at least one object within where field, for example, "login" is queal to "example". How can I do this?
I tried something like this:
export async function getQueues(request: Request, response: Response) {
const returningQueues = await queues.find({order: [login: request.params.login]});
response.json(returningQueues);
But TypeScript error (56 missing properties(mostly internal Mongoose's) of type "User", which I store within an array) says that's I am wrong in my thoughts.
If you just have one condition on the array field, you can simply do:
queues.find({"order.login": request.params.login})
But if you have multiple conditions, you can use $elemMatch:
queues.find({
order: { $elemMatch: { login: request.params.login, name: request.params.name } }
})

How should I fetch data from another collection and join with the result

I have an endpoint which gives me a list of all Profiles available, now I have a Post Schema & Profile Schema, I want to add a list of posts that specific users have made to my result
Code present in endpoint
const profiles = await Profile.find()
.populate('user', [
'name',
'avatar'
])
Profile Schema
const ProfileSchema = new mongoose.Schema({
user: {
type: mongoose.Schema.Types.ObjectId,
ref: 'user'
},
post: [],
........
Post Schema
const PostSchema = new Schema({
user: {
type: Schema.Types.ObjectId,
ref: 'user'
},
text: {
type: String,
required: true
},
........
Response
[
{
"social": {
"youtube": "https://youtube.com/.",
"twitter": "https://twitter.com/.",
"facebook": "https://fb.com/."
},
"post": [], //This should populate
"skills": [
"HTML",
"CSS",
"PHP",
"Ruby"
],
"_id": "5ced6cb9e3f7485ee2cb0445",
"user": {
"_id": "5ced02551b60fe20afc72a32",
"name": "John abc",
"avatar": "//www.gravatar.com/avatar/1f9d9a9efc2f523b2f09629444632b5c?s=200&r=pg&d=mm"
},
"status": "Developer",
"experience": [
{
"current": true,
"_id": "5ceebb30bb0c667b85a94f97",
"from": "2010-08-09T18:30:00.000Z",
"description": "lorem ipasum"
}
],
"date": "2019-05-28T17:15:37.755Z",
"__v": 30,
"bio": "I am dev",
"education": [
{
"current": false,
"_id": "5cf0c1dc6b8dc33cd68be560",
"degree": "BE",
"from": "2005-07-09T18:30:00.000Z",
"to": "2010-03-03T18:30:00.000Z",
"description": "Got BE"
}
]
}
]
Expected output
[
{
"social": {
"youtube": "https://youtube.com/.",
"twitter": "https://twitter.com/.",
"facebook": "https://fb.com/."
},
"post": [
{_id:98as98djakjbkasd,
text:"This is post by xyz user"
},
{_id:234oijaoijd,
text:"This is another post by xyz user"
}
]
"skills": [
"HTML",
"CSS",
"PHP",
"Ruby"
],
"_id": "5ced6cb9e3f7485ee2cb0445",
"user": {
"_id": "5ced02551b60fe20afc72a32",
"name": "John abc",
"avatar": "//www.gravatar.com/avatar/1f9d9a9efc2f523b2f09629444632b5c?s=200&r=pg&d=mm"
},
.....
I want to populate posts done by the same user, what changes are needed to be done in endpoint code.
I am new to mongoose, upon searching for solutions I found aggregate could be useful but it cannot be used like .find().aggregate([...])
Trying to join in MongoDB would defeat the purpose of using MongoDB. As we first think about our use case then decide database and schema. You could however use DBref and write your own application code.
Another thing you can alter your schema into a single collection and use embedded document
It's always a suggestion of MongoDB that avoid join in our query!

I am trying to insert new customer using google reseller api of node.I am getting 400 error

//parmeter
var params = {
"auth":auth,
"kind": "reseller#customer",
"customerId": "customerId",
"customerDomain": "customer domain",
"postalAddress": {
"kind": "customers#address",
"contactName": "John Doe",
"organizationName": "Example Inc",
"postalCode": "94043",
"countryCode": "US",
},
"alternateEmail": "email address "
}
//using api
var service = google.reseller('v1');
service.customers.insert(params,function(err,data){
console.log(err);
console.log(data);
})
Iam getting this error:
{ [Error: Invalid Value]
code: 400,
errors: [ { domain: 'global', reason: 'invalid', message: 'Invalid Value' } ] }
You can use request module to perform this action in easy way.
here is an example to insert a customer execute it
POST https://www.googleapis.com/apps/reseller/v1/customers
Body parameter
{
"kind": "reseller#customer",
"customerId": "custId-1234",
"customerDomain": "example.com",
"postalAddress": {
"kind": "customers#address",
"contactName": "John Doe",
"organizationName": "Example Inc",
"postalCode": "94043",
"countryCode": "US",
},
"alternateEmail": "alternateEmail#google.com"
}
For more reference
The problem is stated in your error logs already.
reason: message: 'Invalid Value'
"auth":auth is not included in the Customers resource.
These are the valid values:
{
"kind": "reseller#customer",
"customerId": string,
"customerDomain": string,
"postalAddress": {
"kind": "customers#address",
"contactName": string,
"organizationName": string,
"locality": string,
"region": string,
"postalCode": string,
"countryCode": string,
"addressLine1": string,
"addressLine2": string,
"addressLine3": string
},
"phoneNumber": string,
"alternateEmail": string,
"resourceUiUrl": string,
"customerDomainVerified": boolean
}

Why is my Mongoose schema missing one of its fields?

This is my schema:
var RegionSchema = new Schema({
"metadata": {
"type": String,
"name": String,
"children": [{
"name": String,
"type": String
}],
"parent": Schema.ObjectId
},
"data": [DataContainer]
});
This is a unit test I am writing, in which I store an instance of this object with some null values:
describe('Region with no data', function() {
it('Should save without error', function(done) {
var emptyRegion = new Region({
"metadata": {
"type": "City",
"name": "San Diego",
"children": [],
"parent": null
},
"data": []
});
emptyRegion.save(function(err, saved) {
console.log(saved)
if (err) throw err;
if (saved.metadata.name === "San Diego")
done();
})
});
});
However, when I try to print out what is saved, I get this:
{ __v: 0, _id: 551cd261cc55c5ff48c8150b, data: [] }
Why is my metadata object not saving? Even before the save call, emptyRegion looks just like that. Am I not defining my metadata correctly?
The annoying culprit is the type field within the metadata subdocument. Mongoose interprets that as meaning that metadata is of type String and has a bunch of irrelevant properties. Change your schema definition to the following and it should work:
var RegionSchema = new Schema({
"metadata": {
"type": {"type": String},
"name": String,
"children": [{
"name": String,
"type": {"type": String}
}],
"parent": Schema.ObjectId
},
"data": [DataContainer]
});
Alternatively, use a different name for your type fields.

How can I return only one client per several cases with mongoose populate?

I'm using mongoose populate to try an create one-to-many relationships within my schemas
var clientSchema = new mongoose.Schema({
name: { type: String, required: true },
title: { type: String, default: "N/S" },
birthDate: { type: Date },
ssn: { type: String, default: "N/S" },
spouse: { type: String, default: "N/S" },
notes: { type: String, default: "N/S" },
address: { type: String, default: "N/S" },
city: { type: String, default: "N/S" },
state: { type: String, default: "N/S" },
zip: { type: String, default: "N/S" },
homePhone: { type: String, default: "N/S" },
workPhone: { type: String, default: "N/S" },
mobilePhone: { type: String, default: "N/S" },
fax: { type: String, default: "N/S" },
email: { type: String, default: "N/S" }
});
var caseSchema = mongoose.Schema({
_client: { type: mongoose.Schema.Types.ObjectId, ref: 'Client' },
name: { type: String, required: true },
lead: { type: String },
priority: { type: String },
dateOpened: { type: Date },
dateAccident: { type: Date },
status: { type: String },
sol: { type: Date },
description: { type: String }
});
What I want to be able to do is query the data base to get all cases with a given _client id.
I have this working but not the way I want it. As of right now, when I use the populate method
from within my route, I'm getting all of the cases with that client id, but I'm also getting
all of the clients, even though all of the clients are the exact same. It seem like this is a waste of resources to return the same client for each case. Is there any way to just return the client once, and then all of the related cases with it?
app.get('/cases/:id', function( req, res ) {
Case
.find( { _client: req.params.id } )
.populate('_client')
.exec( function( err, cases ) {
res.send( cases );
});
});
Here's what I'm getting back:
[
{
"_client": {
"name": "John Doe",
"birthDate": null,
"_id": "51705a7ed0ecd0a906000001",
"__v": 0,
"email": "",
"fax": "",
"mobilePhone": "",
"workPhone": "",
"homePhone": "",
"zip": "",
"state": "",
"city": "",
"address": "",
"notes": "",
"spouse": "",
"ssn": "",
"title": "Mr"
},
"name": "test",
"lead": "",
"priority": "",
"dateOpened": null,
"dateAccident": null,
"status": "",
"sol": null,
"description": "",
"_id": "5170679df8ee8dd615000001",
"__v": 0
},
{
"_client": {
"name": "John Doe",
"birthDate": null,
"_id": "51705a7ed0ecd0a906000001",
"__v": 0,
"email": "",
"fax": "",
"mobilePhone": "",
"workPhone": "",
"homePhone": "",
"zip": "",
"state": "",
"city": "",
"address": "",
"notes": "",
"spouse": "",
"ssn": "",
"title": "Mr"
},
"name": "newest case",
"lead": "",
"priority": "",
"dateOpened": null,
"dateAccident": null,
"status": "",
"sol": null,
"description": "",
"_id": "517067d8806f060b16000001",
"__v": 0
},
{
"_client": {
"name": "John Doe",
"birthDate": null,
"_id": "51705a7ed0ecd0a906000001",
"__v": 0,
"email": "",
"fax": "",
"mobilePhone": "",
"workPhone": "",
"homePhone": "",
"zip": "",
"state": "",
"city": "",
"address": "",
"notes": "",
"spouse": "",
"ssn": "",
"title": "Mr"
},
"name": "adding new case",
"lead": "Me",
"priority": "Urgent",
"dateOpened": null,
"dateAccident": null,
"status": "",
"sol": null,
"description": "",
"_id": "51709a16806f060b16000002",
"__v": 0
}
]
This just doesn't seem right to send all of this bloat to my view to be rendered. Should I even be using populate for one-to-many like this?
All of the examples that I see on mongoose.com are one-to-one, with the exception of embedded documents.
If you don't want the client repeated for each case, you'd be better off separately querying for the client and then combining that result with the result of your Case query (without the populate) in whatever way you need.
BTW, '/cases/:id' is a pretty confusing URL for getting cases by client id and not case id.

Resources