req.params.number is string in expressjs? - node.js

I am writing expressjs app. is req.params.anything always string and not number
suppose if I pass a number for user_id it's typeof is always string.
app.get('user/:user_id', function(req, res){
console.log(typeof req.params.user_id);
});
GET user/21
this logs string.
So is it always type string for req.params.x?

Yes, all params will be strings.
This is extracted from the expressjs route.js:
var val = 'string' == typeof m[i]
? decodeURIComponent(m[i])
: m[i];
So the val will always be a string, since the result of decodeURIComponent is always a string, while m is the result of a RegExp.exec() which returns an array of matched strings, so it's also safe to assume that m[i] will be a string.

Related

How to decode encode string in nodejs

I am receiving below encoded string
"{\"type\":\"recipe\",\"id\":\"1624955566083\",\"entity\":\"loves\",\"count\":1}"
when i am doing like following it gives me undefined for each value. How can i generate JSON object from encoded string ?
const { type, id, entity, count } = JSON.parse(req.body);
console.log(type, id, entity); // All the values are undefined
I have to do JSON.parse(JSON.parse(req.body)) to make it work.

Yup validation convert empty string to default value

In my Yup schema I was my String field name to allow you to pass in any string, an empty string, or nothing at all. If you pass in a string, it passes. If you pass in an empty string or nothing, I want to convert to a default value.
This is the schema that I thought would cover it:
const mySchema = yup.object().shape({
name: yup.string('Name must be a string').max(100, 'Name has a max of 100 characters').default('John Doe')
});
However, if I pass in an empty string '', it does not trigger the default conversion and it just passed through as an empty string. I've tried adding required() but that just makes the line fail if I pass an empty string. I've tried nullable() and trim() but nothing seems to work.
How can I make the default value replace empty strings?
I ended up adding a simple method to transform empty string to undefined which will get picked up in the default:
// Add method
yup.addMethod(yup.string, 'stripEmptyString', function () {
return this.transform((value) => (value === '' ? undefined : value));
});
// Usage
const mySchema = yup.object().shape({
name: yup.string('Name must be a string').stripEmptyString().default('John Doe')
});

NodeJS Express create Mongoose query from string

I have this string:
var filter = '{stamps:{$gte: 2020-11-06 06:42:25.000+01:00, $lte: 2020-11-06 09:52:25.000+01:00}'
Somehow I have to query mongoDB collection with this string.
Message.find(filter, function(err, messages){
if(err){
console.log(err);
}else{
//do something here
}
})
Of course I am getting this error:
ObjectParameterError: Parameter "filter" to find() must be an object, got {stamps:{$gte: 2020-11-06 06:42:25.000+01:00, $lte: 2020-11-06 09:52:25.000+01:00}
is there some way to cast this string to object that will be acceptable to mongoDB?
You could either change the way you construct your query, to pass it as JSON an then use JSON.parse() / JSON.stringify()
// Note the necessary double quotes around the keys
const jsonFilter = '{ "stamps": { "$gte": "2020-11-06 06:42:25.000+01:00", "$lte": "2020-11-06 09:52:25.000+01:00" } }'
const query = JSON.parse(jsonFilter)
Message.find(query, callback)
Or you could introduce another dependency like mongodb-query-parser that can parse the string for you.
const parser = require('mongodb-query-parser')
// Note it still needs double quotes around the dates to run properly
const filter = '{stamps:{$gte: "2020-11-06 06:42:25.000+01:00", $lte: "2020-11-06 09:52:25.000+01:00" } }'
const query = parser(filter)
Message.find(query, callback)
https://runkit.com/5fbd473b95d0a9001a2359b3/5fbd473b98492c001a8bba06
If you can't include the quotes around the values in the string, you can use a regular expression to add them. But keep in mind that this regex is tailored to match this exact date format. If the format can change or you want to also match other data types, you should try to include them in your filter string from the start.
const parser = require("mongodb-query-parser")
const filter = '{stamps:{$gte: 2020-11-06 06:42:25.000+01:00, $lte: 2020-11-06 09:52:25.000+01:00} }'
const filterWithQuotedDates = filter.replace(/(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}(\+\d{2}:\d{2})?)/g, '"$1"')
parser(filterWithQuotedDates)
Message.find(query, callback)
https://runkit.com/5fbd494bcd812c0019b491fb/5fbd4951ebe43f001a5b590a
It should be noted that a common use-case is to pass a MongoDB query via URL params and that there are special packages for that:
https://github.com/Turistforeningen/node-mongo-querystring
https://github.com/fox1t/qs-to-mongo

Mongoose accepts null for Number field

I have a mongoose schema where I'm storing a port number. I also have a default value set for the field.
port:{
type:Number,
default:1234
}
If I don't get any value via my API, it gets set to 1234.
However, If someone sends null, it accepts null and saves to database.
Shouldn't it covert null to 1234? null is not a number! Am I understanding it wrong?
I am considering the solution given here, but I dont want to add extra code for something that should work without it (unless I'm wrong and its not supposed to convert null to 1234)
See the comments in this issue:
https://github.com/Automattic/mongoose/issues/2438
null is a valid value for a Date property, unless you specify required. Defaults only get set if the value is undefined, not if its falsy.
(it's about dates but it can be applied to numbers just as well.)
Your options are to either:
add required to the field
add a custom validator that would reject it
use hooks/middleware to fix the issue
You might get away with a pre-save or post-validate (or some other) hook like this:
YourCollection.pre('save', function (next) {
if (this.port === null) {
this.port = undefined;
}
next();
});
but probably you'll have to use something like:
YourCollection.pre('save', function (next) {
if (this.port === null) {
this.port = 1234; // get it from the schema object instead of hardcoding
}
next();
});
See also this answer for some tricks on how to make null trigger default values in function invocation:
Passing in NULL as a parameter in ES6 does not use the default parameter when one is provided
This is unfortunate that Mongoose cannot be configured to tread null as undefined (with some "not-null" parameter or something like that) because it is sometimes the case that you work with data that you got in a request as JSON and it can sometimes convert undefined to null:
> JSON.parse(JSON.stringify([ undefined ]));
[ null ]
or even add null values where there was no (explicit) undefined:
> JSON.parse(JSON.stringify([ 1,,2 ]));
[ 1, null, 2 ]
As explained in mongoose official docs here
Number
To declare a path as a number, you may use either the Number global constructor or the string 'Number'.
const schema1 = new Schema({ age: Number }); // age will be cast to a Number
const schema2 = new Schema({ age: 'Number' }); // Equivalent
const Car = mongoose.model('Car', schema2);
There are several types of values that will be successfully cast to a Number.
new Car({ age: '15' }).age; // 15 as a Number
new Car({ age: true }).age; // 1 as a Number
new Car({ age: false }).age; // 0 as a Number
new Car({ age: { valueOf: () => 83 } }).age; // 83 as a Number
If you pass an object with a valueOf() function that returns a Number, Mongoose will call it and assign the returned value to the path.
The values null and undefined are not cast.
NaN, strings that cast to NaN, arrays, and objects that don't have a valueOf() function will all result in a CastError.

How to use multiple types in node-elasticsearch-client?

I'm a newbie and working on an ES project (Express JS+ ES+MongoDB ). I'm using https://github.com/richardwilly98/elasticsearch-river-mongodb to do the indexing. The following code is working fine for a single index and type. But I have another type with the same index name ("type" : "file_info"). Is there any way to use multiple types with the same index name ?
For example- var type= ["stu_info", "file_info"].
var index = "studentdb";
var type = "stu_info";
var elasticSearchClient = new ElasticSearchClient(serverOptions);
elasticSearchClient.search(index, type, qryObj).
on('data', function (data) {
console.log(data)
})
Simply concatenate the types with a comma:
var type = 'my_type,my_other_type,my_third_type';
elasticSearchClient.search('my_index_name', type, qryObj)
.on('data', function(data) {
console.log(JSON.parse(data))
})
.exec();
Elasticsearch.js API has search method.
type: String, String[], Boolean — A comma-separated list of document types to search; leave empty to perform the operation on all types.
[search Api][1]https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/api-reference.html#api-search

Resources