Add key in Joi object if key does not exist - node.js

I have a joi schema like this
Joi.object({
name: Joi.string(),
language: Joi.string(),
birthday: Joi.date(),
age: Joi.number().integer()
})
The input can contain birthday and age at the same time or just one of the keys. If one of the keys does not exist, I want the missing key to be automatically added with the string "NULL" like this
//input
{
"name": "Jane Doe",
"language": "de",
"birthday": "1960-06-27"
}
//modified to
{
"name": "Jane Doe",
"language": "de",
"birthday": "1960-06-27",
"age": "NULL"
}
Is there a way to automatically add a key with a default value, if the key is missing?

Use any.default([value]):
const schema = Joi.object({
name: Joi.string(),
language: Joi.string(),
birthday: Joi.date(),
age: Joi.number().integer().default(null)
});
console.log(schema.validate({
"name": "Jane Doe",
"language": "de",
"birthday": "1960-06-27"
}));
Output:
{
name: "Jane Doe",
language: "de",
birthday: Mon Jun 27 1960 01:00:00 GMT+0100 (Central European Standard Time),
age: null
}
I would prefer null rather then a string "NULL" because both date and age are not of type string.

Related

Scope Results in mongoose by date

I'm having a hard time trying to achieve this results for days. I hope someone can help me here.
Results I want to achieve. Btw I'm using mongoose/mongodb/node.js
{
"2020-01-12": [
{
"user_id": 1234,
"firstName": "John Doe"
"createdAt": 2021-01-12T05:45:50.898Z
},
{
"user_id": 1233,
"firstName" "Jane Doe",
"createdAt": 2021-01-12T06:45:50.898Z
}
],
"2020-01-13": [
{
"user_id": 1232,
"firstName" "Jeff Doe",
"createdAt" 2021-01-13T05:45:50.898Z
}
]
}
My sample schema
const User = {
table: 'User',
schema: {
_id: {
name : 'Id',
type: db.keyType(),
required: true
},
firstName: {
name: 'FirstName',
type: String,
required: true,
}
}
Here's my sample code.
Users.find({ createdAt: { $gte: startDate, $lte: endDate.setHours(endDate.getHours() + 23) }}).sort({ createdAt: 'asc'}).then(results => {
res.status(200).json({
results
})
URL: api/users/days/?start_date=2021/01/12&end_date=2021/01/15
I want to scope my data by date but I can't achieve it using mongoose. Thanks in advance if you can help me with this. Its okay if you can help me understand the logic on how to achieve so I can fully understand what I need to learn to get this results so I can research for it. ty very much
Also my **date format is like this ** 2021-01-13T05:45:50.898Z

Json values from one file, based on fields from another Json file

I am trying to get values to a JSON file, based on field mapping from another JSON file.
I have a JSON file I get from external systems, which have different field names. I created a JSON file that will map the fields from the external system to the names I need the fields to be in:
{
"username":"user",
"externalSystemId":"id",
"active":"active",
"type":"type",
"patronGroup":"group",
"meta": {
"creation_date":"dateCreated",
"last_login_date":"lastLogin"
},
"personal": {
"lastName":"lname",
"firstName":"fname",
"email":"email",
"phone":"phone",
"mobilePhone":"mobile",
"dateOfBirth":"birthDate",
"addresses":{
"countryId": "countryCode",
"addressLine1": "address",
"addressLine2": "address2",
"city": "city",
"region": "region",
"postalCode": "zipcode",
"addressTypeId": "addressType",
"primaryAddress": "primary"
}
},
"enrollmentDate": "enrollmentDate",
"expirationDate": "expirationDate"
}
In this file, the fields are the fields I will need to populate, while the values are the names of the fields I get from the external system, which looks like this for example:
{
"user":"name",
"id":12345,
"active":true,
"type":"Student",
"group":"BA",
"dateCreated":"NOV 22 2019",
"lastLogin":"NOV 23 2020",
"lname":"Yard",
"fname":"Paul",
"email":"email#gmail.com",
"phone":"(000)-000-0000",
"mobile":"(000)-000-0000",
"birthDate":"OCT 11 1999",
"countryId": "US",
"addressLine1": "4th street",
"addressLine2": "25B",
"city": "NY",
"region": "NY",
"postalCode": "00000",
"addressTypeId": "Personal",
"primaryAddress": true,
"enrollmentDate": "MAR 22 2019",
"expirationDate": "MAR 21 2022"
}
So the end JSON file will need to look like this:
{
"username":"name",
"externalSystemId":12345,
"active":true,
"type":"Student",
"patronGroup":"BA",
"meta": {
"creation_date":"NOV 22 2019",
"last_login_date":"NOV 23 2020"
},
"personal": {
"lastName":"Yard",
"firstName":"Paul",
"email":"email#gmail.com",
"phone":"(000)-000-0000",
"mobilePhone":"(000)-000-0000",
"dateOfBirth":"OCT 11 1999",
"addresses":{
"countryId": "US",
"addressLine1": "4th street",
"addressLine2": "25B",
"city": "NY",
"region": "NY",
"postalCode": "00000",
"addressTypeId": "Personal",
"primaryAddress": true
}
},
"enrollmentDate": "MAR 22 2019",
"expirationDate": "MAR 21 2022"
}
I was thinking of using a dictionary/index to create this, but I've never done that before, nor am I sure how to do it.
Is there a simple way to do it?
This kind of mapping is easy with a dictionary when we have single level of JSON.
For a multi level JSON, we can make use of a recursive function to map the data from dictionary.
In the code lets say this is your JSON:
let json = {
username: "user",
externalSystemId: "id",
active: "active",
type: "type",
patronGroup: "group",
meta: {
creation_date: "dateCreated",
last_login_date: "lastLogin",
},
personal: {
lastName: "lname",
firstName: "fname",
email: "email",
phone: "phone",
mobilePhone: "mobile",
dateOfBirth: "birthDate",
addresses: {
countryId: "countryCode",
addressLine1: "address",
addressLine2: "address2",
city: "city",
region: "region",
postalCode: "zipcode",
addressTypeId: "addressType",
primaryAddress: "primary",
},
},
enrollmentDate: "enrollmentDate",
expirationDate: "expirationDate",
};
// Here is the dictionary:
// Note: the personal address field had incorrect mapping for few fields, I have modified the property to match the value of respective key of the JSON.
let dictionary = {
user: "name",
id: 12345,
active: true,
type: "Student",
group: "BA",
dateCreated: "NOV 22 2019",
lastLogin: "NOV 23 2020",
lname: "Yard",
fname: "Paul",
email: "email#gmail.com",
phone: "(000)-000-0000",
mobile: "(000)-000-0000",
birthDate: "OCT 11 1999",
countryCode: "US",
address: "4th street",
address2: "25B",
city: "NY",
region: "NY",
zipcode: "00000",
addressType: "Personal",
primary: true,
enrollmentDate: "MAR 22 2019",
expirationDate: "MAR 21 2022",
};
// recursive function to map the JSON, extract the actual value from from dictionary
function buildMapping(jsonParam) {
let result = {};
// iterate over the JSON parameter
for (const [key, value] of Object.entries(jsonParam)) {
if (typeof value === "object") {
// for type as object, make a recursive call with the object value as param
// collect the result of inner object
let resultInner = buildMapping(value);
// attach the result of the inner object to its key
result[key] = resultInner;
} else {
// check if the dictionary contains the mapping, otherwise set as null
result[key] = dictionary.hasOwnProperty(value)
? dictionary[value]
: null;
}
}
return result;
}
let resultJson = buildMapping(json);
console.log(resultJson);
Result:
{
username: "name",
externalSystemId: 12345,
active: true,
type: "Student",
patronGroup: "BA",
meta: { creation_date: "NOV 22 2019", last_login_date: "NOV 23 2020" },
personal: {
lastName: "Yard",
firstName: "Paul",
email: "email#gmail.com",
phone: "(000)-000-0000",
mobilePhone: "(000)-000-0000",
dateOfBirth: "OCT 11 1999",
addresses: {
countryId: "US",
addressLine1: "4th street",
addressLine2: "25B",
city: "NY",
region: "NY",
postalCode: "00000",
addressTypeId: "Personal",
primaryAddress: true,
},
},
enrollmentDate: "MAR 22 2019",
expirationDate: "MAR 21 2022",
};

how can I add multiple travels information?

Here is my json data, I want to insert multiple travels information in travelers. Total numbers of travels may be given by the user.
In the below format I can just add one traveler.
return amadeus.booking.flightOrders.post(
JSON.stringify({
'data':{
'type': 'flight-order',
'flightOffers': [response.data.flightOffers[0]],
'travelers':[{
"id": 1,
"name": {
"firstName": req.body.firstname,
"lastName": req.body.lastname
},
"gender": req.body.gender,
"contact": {
"emailAddress": req.body.emailaddress,
"phones": [{
"deviceType": req.body.devicetype,
"countryCallingCode": req.body.countrycallingcode,
"number": req.body.number
}]
},
"documents": [{
"documentType": req.body.documentype,
"birthPlace": req.body.birthplace,
"issuanceLocation": req.body.issuancelocation,
"issuanceDate": req.body.issuancedate,
"number": req.body.p_number,
"expiryDate": req.body.expirydate,
"issuanceCountry": req.body.issuancecountry,
"validityCountry": req.body.validitycountry,
"nationality": req.body.nationality,
"holder": true
}]
}]
}
})
);
}).then(function (response)
travelers is an array. You can push multiple entries to it like
data.travelers.push(traveler);
You can run get multiple traveler details in your API like:
{
"travelers": [{
"firstname": "John",
"secondname": "Doe",
}, {
"firstname": "Jane",
"secondname": "Doe",
}]
}
This can then be looped over to push multiple travelers in the data variable.
let id = 1;
req.body.travelers.forEach(traveler => {
data.travelers.push({
id: id++,
name: {
firstName: traveler.firstname,
lastName: traveler.lastname
}
});
});

Mongoose - search in array with array

I have following model
var reservationSchema = new Schema({
lcode: Number,
reserved_days: [daySchema],
});
var daySchema = new Schema({
pk: Number,
date: String,
price: Number,
payment_type: String,
payment_date: String,
room: { room_id: String, name: String }
});
I have a reservation with array of reserved_days. I need to compare this reservation and reservations in database and find reservation where at least one reserved_days date or reserved_days room.room_id are the same that contains in array. Array must not be fully equal, I just need to find duplicate days.
Now I try the following
Reservation.find({
$or: [{
"reserved_days.room.room_id": {
$in: req.body.reservation.reserved_days
}
}, {
"reserved_days.date": {
$in: req.body.reservation.reserved_days
}
}]
}).exec(function(err, found)
but it doesn't work.
Test request reservation.reserved_days object looks the following
"reserved_days": [
{
"pk": 3543,
"date": "2018-07-14",
"price": 3213.0,
"payment_type": "Безналичный расчет",
"payment_date": "2017-12-28",
"room": {
"room_id": "7",
"name": "Стандарт"
}
},
{
"pk": 3544,
"date": "2018-07-15",
"price": 3213.0,
"payment_type": "Безналичный расчет",
"payment_date": "2017-12-28",
"room": {
"room_id": "7",
"name": "Стандарт"
}
}]
Is it possible to do ?

Model not returning what is expected

I have 2 mongoose Models/Schemas (Products & Merchants). When doing a .find() on Products it is returning all products, as expected but when doing it for Merchants it is returning everything (both merchant and product data) when it should just be returning merchants based off the defined schema. I have one collection on my mongoDB server which contains all my merchants and the products.
Any idea what I am missing?
Thanks
Merchants Model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var MerchantShema = new Schema({
merchants: [{
merchant_id: Number,
price_current: Number,
price_rrp: Number,
aff_link: String,
merchant_product_id: Number,
aw_image_url: String,
cost_scoop: String,
created_at: Date,
updated_at: Date
}]
});
module.exports = mongoose.model('Merchants', MerchantShema, 'products');
Products Model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ProductSchema = new Schema({
ean: Number,
aw_product_id: Number,
product_name: String,
product_brand: String,
product_description: String,
img_sml: String,
img_lrg: String,
cat: String,
sub_cat: String,
weight: String,
rating: String,
created_at: Date,
updated_at: Date,
merchants: [{
merchant_id: Number,
price_current: Number,
price_rrp: Number,
aff_link: String,
merchant_product_id: Number,
aw_image_url: String,
cost_scoop: String,
created_at: Date,
updated_at: Date
}],
nutrition: [{
calories: Number,
protein: Number,
fat: Number,
sat_fat: Number,
carbs: Number,
sugar: Number,
salt: Number,
calories: Number
}],
ingredients: String,
flavours: String,
is_active: Boolean
});
module.exports = mongoose.model('Products', ProductSchema, 'products');
My Routes
app.get('/api/products', function(req, res) {
Products.find(function(err, products){
if (err) return console.error(err);
return res.send(products);
})
.where('is_active').equals('true')
});
app.get('/api/merchants', function(req, res){
Merchants.find(function(err, merchants){
if (err) return console.error(err);
return res.send(merchants);
});
});
Example of my collection
[
{
"_id": "55840f86e4b0ba19c15ee26d",
"merchant_id": "1111",
"merchant_aw_id": "1",
"merchant_name": "test merchant",
"merchant_url": "google.com",
"merchant_image": "",
"created_at": "",
"updated_at": "",
"merchants": []
},
{
"_id": "558426f9e4b0ba19c15ee495",
"ean": "123456789",
"aw_product_id": "55555",
"product_name": "Test Product",
"product_brand": "Test Brand",
"product_description": "This is a description for the test product",
"img_sml": "http://images.productserve.com/preview/6/3196/73/20/704322073.jpg",
"img_lrg": "http://images.productserve.com/preview/6/3196/73/20/704322073.jpg",
"cat": "Protein",
"sub_cat": "Protein",
"weight": "2.5kg",
"rating": "5",
"created_at": "",
"updated_at": "",
"nutrition": [
{
"salt": "1",
"sugar": "1",
"carbs": "1",
"sat_fat": "1",
"fat": "1",
"protein": "1",
"calories": "1"
}
],
"ingredients": "",
"flavours": "",
"is_active": "true",
"merchants": [
{
"merchant_id": 1111,
"price_current": 9.99,
"price_rrp": 15.99,
"aff_link": "google.com",
"merchant_product_id": 999,
"aw_image_url": "",
"cost_scoop": "43p",
"created_at": "",
"updated_at": ""
}
]
},
{
"ean": "123456789",
"aw_product_id": "55555",
"product_name": "Test Product",
"product_brand": "Test Brand",
"product_description": "This is a description for the test product",
"img_sml": "http://images.productserve.com/preview/6/3196/73/20/704322073.jpg",
"img_lrg": "http://images.productserve.com/preview/6/3196/73/20/704322073.jpg",
"cat": "Protein",
"sub_cat": "Protein",
"weight": "2.5kg",
"created_at": "",
"updated_at": "",
"nutrition": [
{
"salt": "1",
"sugar": "1",
"carbs": "1",
"sat_fat": "1",
"fat": "1",
"protein": "1",
"calories": "1"
}
],
"ingredients": "",
"flavours": "",
"is_active": "true",
"merchants": [
{
"merchant_id": 1111,
"price_current": 9.99,
"price_rrp": 15.99,
"aff_link": "google.com",
"merchant_product_id": 999,
"aw_image_url": "",
"cost_scoop": "43p",
"rating": "5",
"created_at": "",
"updated_at": ""
}
]
}
]
In looking at your merchants model definition. You are calling products in your export:
module.exports = mongoose.model('Merchants', MerchantShema, 'products');
This should probably read
module.exports = mongoose.model('Merchants', MerchantShema, 'merchants');
Another thing I noticed is that you have two keys called "calories".
I ran the code and it now brings back merchants correctly. However, when you call products, it brings back the merchant as part of that schema, since merchants are included in products. Another way you can do this is to use a nested schema. You can read about those in this other thread: Mongoose subdocuments vs nested schema
Hope that helps.

Resources