Problem in handling many field through function in mongoose - javascript

I want to generate field in mongoose with function.
Because there are many fields, but they are much the same, I wanna use function to create them to keep code short.
I wrote a function, but there exists lints.
import { Schema } from 'mongoose'
function fieldGen(name, type="string", isRequired=true) {
var field = {}
field[name] = {
type: type,
required: isRequired
}
return {...field}
}
const testSchema = new Schema({
fieldGen("firstname")
fieldGen("lastname")
fieldGen("location")
})
In VS Code, Problem shows as below
Identifier expected. ts(1003) [20, 12]
I expect first argument "firstname" matches name in function, and return object.

You're adding values to your testSchema object without giving them names.
Also, you're spreading the properties of the field object into a new object literal. That doesn't accomplish anything. Just returning the field object would yield the same result.
I see what you are trying to do. If you debug this in smaller steps and take a closer look at the data you are handling, I think you'll figure it out on your own.

Related

How to define a Date Scalar using GraphQL-JS?

I am trying to define a custom scalar in GraphQL so I can query & process the Dates in my MongoDB collections. I am not sure I understand 100% what a scalar is or does, but it seems to be a sort of type that I define myself. All the examples & tutorials I found were using Apollo or some other type of notation, but I would like to see a solution using GraphQL-JS
So far, I have defined my scalar like so:
const Date = new GraphQLScalarType({
name: "Date",
serialize: (value) => {
return value; //is it correct, to just return the value? Do I need to parse it or turn it into a Date first?
},
parseValue: () => {
return "serialise"; //I am just returning this string here, because I do not know what this function is for
},
parseLiteral(ast) {
return null; //I am just returning null here, because I do not know what this function is for
},
});
I am not sure I understand what each of these functions are supposed to do. And wouldn't there also have to be a deserialize function?
When I query now against my graphql endpoint I do get back something like:
{
"myDate": "2020-07-15T00:00:00.000Z"
}
I guess that my serialise function is at play here? The Date is certainly correct, but I am not sure if I should do anything else with the data before returning it from serialize? Right now I just return whatever I get from my MongoDB database.
Urigo, from The Guild, created graphql-scalars that contains definitions for multiple common scalars used in GraphQL
//is it correct, to just return the value? Do I need to parse it or turn it into a Date first?
It would be wise to validate that value is a Date before returning it.
And yes, just return the value.
//I am just returning null here, because I do not know what this function is for
This is the entry from the abstract-syntax-tree (ast).
See Urigo's code below to see how the ast object is accessed
ast.kind
ast.value
Additionally, take a look at this SO post that describes the difference between parseValue and parseLiteral
Take a look at localDate and that may provide you the example you need to answer your question :)
https://github.com/Urigo/graphql-scalars/blob/master/src/scalars/LocalDate.ts#L34
export const GraphQLLocalDate = /*#__PURE__*/ new GraphQLScalarType({
name: 'LocalDate',
description:
'A local date string (i.e., with no associated timezone) in `YYYY-MM-DD` format, e.g. `2020-01-01`.',
serialize(value) {
// value sent to client as string
return validateLocalDate(value);
},
parseValue(value) {
// value from client as json
return validateLocalDate(value);
},
parseLiteral(ast) {
// value from client in ast
if (ast.kind !== Kind.STRING) {
throw new GraphQLError(
`Can only validate strings as local dates but got a: ${ast.kind}`,
);
}
return validateLocalDate(ast.value);
},
});

_.matchesProperty shorthand in Lodash not working but providing function does

I'm pretty new to Lodash and I'm having some problems with the shorthand notation on the _.find function.
I have the following angular 2 object:
export class ProductData {
id: number;
name: string;
description: string;
type: ProductTypeData;
}
I then have an array of ProductData that I created by filtering on product type. I use this array to display values in a dropdown list on to the user. When the user selects a product from the dropdown list I am storing the id in a local variable, productId. When the user closes the dialog I am doing processing on the selected product.
The following code works for me:
var self = this;
let selectedProduct = _.find(this.filteredProducts, function(product) { return product.id == self.productId; });
I would rather use the _.matchesProperty shorthand for Lodash (since it's cleaner to read than assigning the context to a variable) like so:
let selectedProduct = _.find(this.filteredProducts, ['id', this.productId]);
but that is returning undefined for me.
I'm guessing I'm screwing up something fairly simple but I cannot, for the life of me, figure out what.

How to set default module params in Javascript

so i'm trying my hands on writing my very first library module using pure javascript except that i just hit a snag and need a little bit of help.
I'm using Revealing module pattern because of its neatness. In my module i have my default params in an object like this.
var defaults = {
name : 'John Doe',
age : 'Unspecified,
height : '5feet'
};
And this works splendid, but i have an init function where a user can pass an object with these keys. e.g
Module.init({
name : 'james',
age : 12
});
Now in my code, i try to write a function that returns the values of each of these keys comparing the default values and the initialized one. If the key/value exists initialized, it should return it else use default. I know what i want, but don't know how to check the objects keys just yet.
function getValues (defaultObject, initObject){
//scans the keys and returns the values
}
So in code i can do stuff like
var options = getValues(defaultObject, initObject);
var name = options.name;
This means that name will either be james if specified or john doe if not. Also for height since i didn't set a value, i get the default too
Thanks in advance guys.
What you need to do to compare both objects keys, and if the new object has a key, then replace the value in the old one. Here's an example:
function getValues(defaultObject, initObject) {
for (var key in initObject) {
if (initObject.hasOwnProperty(key)) {
defaultObject[key] = initObject[key];
}
}
return defaults;
}
I hope this help you.
See my answer in another thread how to
better define function optional default params : https://stackoverflow.com/a/52082835/1422407
It may help you to redefine function signature, and as result less useless logic in function itself.

References in MongoDB / Mongoose / nodejs - parallelization

I want to get references in mongoDB using nodejs/mongoose.
In the documentation I read that there are two options: Manual References or DBRefs.
Since they state, its recommended to use Manual References, I decided to set up a schema in the following way:
var schema = new mongoose.Schema({
name : String,
reference : mongoose.Schema.ObjectId
});
Question: If I retrieve an array of these objects from my collection, how do I resolve the references in a good practice way?
My Idea was to use Nimble and parallelize the necessary requests. I wanted to do something like
flow.parallel(functions, function() {
return result;
});
where I dynamically fill an array of functions
var functions = []
which I pass then to nimble.
(kind of this SO-question: Javascript Array of Functions)
Question: Is this practical? The array of functions-thing seems kind of not really the way to go to me. But I don't see any alternative, since nimble needs to be called with a static number of functions.
You can use Mongoose's support for reference population to efficiently follow references.
var schema = new mongoose.Schema({
name : String,
reference : { type: mongoose.Schema.ObjectId, ref: 'OtherModel' }
});
var MyModel = mongoose.model('MyModel', schema);
MyModel.find().populate('reference').exec(function(err, docs) {...});
In the above example, the reference field of each docs element gets populated with referenced doc.

Is there a native feature to convert string based JSON into Mongoose Schema object instance?

I am using Express and I am looking for a convenient way to convert this kind of object (which comes on the request req.body.myObject):
{
"name": "Foo",
"someNumber": "23",
"someBoolean": "on"
}
Into an instance of this Schema:
var myObjectSchema = new Schema({
name: String,
someNumber: Number,
someBoolean: Boolean
});
Notice that the first object comes from the request, so its made entirely by Strings.
Is there some nice way to achieve this? If not, would you have any suggestions on how to implement this feature as a middleware???
By referring to this thread Mongoose : Inserting JS object directly into db I figured out that yes, theres a built in feature for this.
You simply build a new model passing request values (from the form) as parameters:
function add(req, res){
new Contact(req.body.contact).save(function(err){
console.log("Item added");
res.send();
});
};
It automatically converts stuff for you!
I know this answer has already been accepted, but I wanted to point out that mongoose takes care of most of the casting for you... most of the time. While it's convenient that mongoose does this, it abstracts away the true behavior of mongo. For example, mongoose lets you do something like this:
PersonModel.findById("4cdf00000000000000007822", ...);
However, if you tried to query the database directly (without mongoose), this would not work:
PersonCollection.find({_id: "4cdf00000000000000007822"}, ...);
This is because ObjectIds are not strings... they are objects. Internally, mongoose converts that string to an ObjectId and then performs a query against the database so that the final query looks kinda like this:
PersonCollection.find({_id: ObjectId("4cdf00000000000000007822")}, ...);
Also, each path in a schema has a "caster" method. This is a private method, but it's darn handy when you need it. PLEASE NOTE THAT THE caster METHODS DESCRIBED BELOW ARE UNDOCUMENTED AND CAN CHANGE WITHOUT WARNING. USE AT YOUR OWN RISK (sorry for yelling):
// Use PersonModel.schema.paths() to get all paths and loop over them if you want
var key = "name";
var pathObj = PersonModel.schema.path( key );
if( !pathObj ) pathObj = PersonModel.schema.virtualpath( key );
if( !pathObj ) { /* not found: return, continue, exit, whatever */ }
// UNDOCUMENTED: USE AT YOUR OWN RISK
var caster = pathObj.caster || pathObj;
var castedValue = caster.cast( req.body.name );
Why do I know this? Because if you want to use some of the more advanced features of mongo such as aggregation, you will need to cast your own values as you build the pipeline. I have also needed to manually cast values for certain queries which used the $in operator... maybe this is not needed any more. Point is, if you are having trouble getting the results you expect, try casting the values yourself.
Provided the schema is static, one could theoretically go the lazy, non-sophisticated way and just hardcode the values instead of passing the object itself:
var someObject = {
name: "Foo",
someNumber: "23",
someBoolean: "on"
}
var myObjectSchema = new Schema({
name: someObject.name,
someNumber: parseInt(someObject.someNumber, 10),
someBoolean: (someObject.someBoolean == "on")
});
Possibly not the answer you were looking for, but might be something to consider if nothing better is available.

Categories

Resources