146 lines
5.1 KiB
JavaScript
146 lines
5.1 KiB
JavaScript
const router = require("express").Router();
|
|
const _ = require('lodash')
|
|
const getSearchPresets = require("../models/getSearchPresets.js");
|
|
const base64 = require("../util/base64.js")
|
|
const sas = require("../util/scoreAndSearch.js");
|
|
const oldToNewQuerySyntax = require("../util/oldToNewQuerySyntax.js")
|
|
const getRegions = require('../models/getRegions.js')
|
|
|
|
|
|
module.exports = dbConn => {
|
|
router.get("/api/v1/search", searchHandler(dbConn));
|
|
router.get("/api/v1/search/presets", presetHandler(dbConn));
|
|
|
|
return router;
|
|
};
|
|
|
|
function presetHandler(dbConn) {
|
|
return function (req, res) {
|
|
getSearchPresets(dbConn).then(presets => {
|
|
res.json(presets)
|
|
}).catch(error => {
|
|
// TODO error handling
|
|
})
|
|
}
|
|
}
|
|
|
|
function searchHandler(dbConn) {
|
|
const scoreAndSearch = sas(dbConn)
|
|
return async function (req, res) {
|
|
let response = {}
|
|
|
|
response.meta = {
|
|
params: req.params,
|
|
query: req.query,
|
|
headers: req.headers
|
|
}
|
|
|
|
// SWITCH TO SUPPORT OLD AND NEW BASE64 BASED QUERY SYNTAX
|
|
let q = req.query.q ? base64.base64ToObj(req.query.q) : req.query
|
|
console.log('Q:', q)
|
|
|
|
// transform syntax and seperate climate queries from price queries
|
|
if (!req.query.q) {
|
|
q = oldToNewQuerySyntax(q)
|
|
}
|
|
// CHOOSE PARAMS WHICH SHALL BE PASSED TO SCORE AND SEARCH
|
|
let scoreQueryObj = prepareQueries(q)
|
|
|
|
let data = await getRegions(dbConn)
|
|
|
|
// FILTER if query contains filterString
|
|
if (q.textfilter) {
|
|
data = filterByString(data, q.textfilter, q.fulltext)
|
|
}
|
|
|
|
scoreAndSearch(data, q.from, q.to, scoreQueryObj).then(searchResults => {
|
|
|
|
//response.data = searchResults
|
|
const cutScores = !(_.isEmpty(scoreQueryObj.climate) && _.isEmpty(scoreQueryObj.costs) && _.isEmpty(scoreQueryObj.others))
|
|
|
|
// only dev:
|
|
if (process.env.SHOW_MATCH_VALUE === '1') searchResults.forEach(reg => reg.name = `${reg.name} (${_.round(reg.score * 10, 1)}% match)`)
|
|
|
|
// FILTER NULLSCORES
|
|
if (!_.get(q, 'showRegionsWithNullScore', false)) {
|
|
console.log('without null scores');
|
|
searchResults.forEach(el => console.log('region:', el.name, 'score:', el.score))
|
|
searchResults = searchResults.filter(el => !_.some(el.scores, score => _.isNaN(score.score) || _.isNil(score.score) || score.score <= 0))
|
|
// searchResults = searchResults.filter(el => !(_.isNil(el.score) || _.isNaN(el.score)) )
|
|
// searchResults = searchResults.filter(el => {
|
|
// let nullcnt = 0
|
|
// el.scores.forEach(sc => {
|
|
// if (_.isNaN(sc.score) || sc.score <= 0 || _.isNil(el.score)) {
|
|
// nullcnt++
|
|
// }
|
|
// })
|
|
// console.log(el.name, nullcnt)
|
|
// return nullcnt >= 2 ? false : true
|
|
// })
|
|
|
|
/*searchResults = searchResults.filter(el => {
|
|
console.log('scorrrrrr', el.score);
|
|
let keepIt = true
|
|
//if (_.some(el.scores, score => score.score <= 0) && el.score < 1) keepIt = false
|
|
return cutScores ? keepIt : true
|
|
})//.filter(el => !_.isNaN(el.score))*/
|
|
}
|
|
// SEND RESPONSE
|
|
if (_.isEmpty(searchResults)) {
|
|
res.status(204).json(searchResults)
|
|
return
|
|
}
|
|
// response.data = searchResults
|
|
// res.json(response)
|
|
res.json(searchResults)
|
|
|
|
}).catch(e => {
|
|
// TODO error handling
|
|
console.log(e)
|
|
res.status(400).send(e.message)
|
|
})
|
|
}
|
|
}
|
|
|
|
function filterByString(searchResults, filterString, boolFulltext) {
|
|
return _.filter(searchResults, region => {
|
|
// console.log("filtering: filterString, boolFulltext");
|
|
// console.log(filterString, boolFulltext);
|
|
filterString = filterString.toLowerCase()
|
|
let name = region.name.toLowerCase()
|
|
let country = region.country.toLowerCase()
|
|
if (boolFulltext) {
|
|
let desc = region.description.toLowerCase()
|
|
return name.includes(filterString) || country.includes(filterString) || desc.includes(filterString)
|
|
}
|
|
return name.includes(filterString) || country.includes(filterString)
|
|
})
|
|
}
|
|
|
|
function prepareQueries(queries) {
|
|
let q = {
|
|
climate: {},
|
|
costs: {},
|
|
others: {}
|
|
}
|
|
// climate
|
|
if (queries.temperature_mean_max) q.climate.temperature_mean_max = queries.temperature_mean_max
|
|
if (queries.precipitation) q.climate.precipitation = queries.precipitation
|
|
if (queries.rain_days) q.climate.rain_days = queries.rain_days
|
|
if (queries.sun_hours) q.climate.sun_hours = queries.sun_hours
|
|
|
|
// costs
|
|
if (queries.accommodation_costs) q.costs.accommodation_costs = queries.accommodation_costs
|
|
if (queries.food_costs) q.costs.food_costs = queries.food_costs
|
|
if (queries.alcohol_costs) q.costs.alcohol_costs = queries.alcohol_costs
|
|
if (queries.water_costs) q.costs.water_costs = queries.water_costs
|
|
if (queries.local_transportation_costs) q.costs.local_transportation_costs = queries.local_transportation_costs
|
|
if (queries.entertainment_costs) q.costs.entertainment_costs = queries.entertainment_costs
|
|
if (queries.average_per_day_costs) q.costs.average_per_day_costs = queries.average_per_day_costs
|
|
|
|
// others
|
|
if (queries.avg_price_relative) q.others.avg_price_relative = queries.avg_price_relative
|
|
|
|
return q
|
|
}
|