More work on search
This commit is contained in:
parent
f4f0c59552
commit
8ed2296b2f
|
@ -1,84 +1,21 @@
|
|||
const express = require('express')
|
||||
const getAssetPaths = require('./npm/getAssetPaths')
|
||||
const npmSearchIndex = require('./npm/searchIndex')
|
||||
|
||||
function enhanceHit(hit) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const assetPaths = getAssetPaths(hit.name, hit.version)
|
||||
|
||||
if (assetPaths) {
|
||||
// TODO: Double check the package metadata to ensure the files
|
||||
// haven't moved from the paths in the index?
|
||||
hit.assets = assetPaths.map(function (path) {
|
||||
return `https://unpkg.com/${hit.name}@${hit.version}${path}`
|
||||
})
|
||||
|
||||
resolve(hit)
|
||||
} else {
|
||||
resolve(hit)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function byRelevanceDescending(a, b) {
|
||||
// Hits that have assets are more relevant.
|
||||
return a.assets ? (b.assets ? 0 : -1) : (b.assets ? 1 : 0)
|
||||
}
|
||||
const npmSearch = require('./npm/search')
|
||||
|
||||
function createSearchServer() {
|
||||
const app = express()
|
||||
|
||||
app.get('/', function (req, res) {
|
||||
const { query, page = 0 } = req.query
|
||||
const hitsPerPage = 20
|
||||
|
||||
if (!query)
|
||||
return res.status(403).send({ error: 'Missing ?query parameter' })
|
||||
|
||||
const params = {
|
||||
typoTolerance: 'min',
|
||||
attributesToRetrieve: [
|
||||
'name',
|
||||
'version',
|
||||
'description',
|
||||
'owner'
|
||||
],
|
||||
attributesToHighlight: null,
|
||||
restrictSearchableAttributes: [
|
||||
'name',
|
||||
'description'
|
||||
],
|
||||
hitsPerPage,
|
||||
page
|
||||
}
|
||||
|
||||
npmSearchIndex.search(query, params, function (error, value) {
|
||||
if (error) {
|
||||
console.error(error)
|
||||
res.status(500).send({ error: 'There was an error executing the search' })
|
||||
} else {
|
||||
Promise.all(
|
||||
value.hits.map(enhanceHit)
|
||||
).then(function (hits) {
|
||||
hits.sort(byRelevanceDescending)
|
||||
|
||||
const totalHits = value.nbHits
|
||||
const totalPages = value.nbPages
|
||||
|
||||
res.send({
|
||||
query,
|
||||
page,
|
||||
hitsPerPage,
|
||||
totalHits,
|
||||
totalPages,
|
||||
hits
|
||||
})
|
||||
npmSearch(query, page).then(function (result) {
|
||||
res.send(result)
|
||||
}, function (error) {
|
||||
console.error(error)
|
||||
res.status(500).send({ error: 'There was an error executing the search' })
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
return app
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
const semver = require('semver')
|
||||
const assetPathsIndex = require('./assetPathsIndex')
|
||||
|
||||
function getAssetPaths(packageName, version) {
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
const searchIndex = require('./searchIndex')
|
||||
const getAssetPaths = require('./getAssetPaths')
|
||||
|
||||
function enhanceHit(hit) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const assetPaths = getAssetPaths(hit.name, hit.version)
|
||||
|
||||
if (assetPaths) {
|
||||
// TODO: Double check the package metadata to ensure the files
|
||||
// haven't moved from the paths in the index?
|
||||
hit.assets = assetPaths.map(function (path) {
|
||||
return `https://unpkg.com/${hit.name}@${hit.version}${path}`
|
||||
})
|
||||
|
||||
resolve(hit)
|
||||
} else {
|
||||
resolve(hit)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function byRelevanceDescending(a, b) {
|
||||
// Hits that have assets are more relevant.
|
||||
return a.assets ? (b.assets ? 0 : -1) : (b.assets ? 1 : 0)
|
||||
}
|
||||
|
||||
// add concatenated name for more relevance for people spelling without spaces
|
||||
// think: createreactnative instead of create-react-native-app
|
||||
function concat(string) {
|
||||
return string.replace(/[-/@_.]+/g, '')
|
||||
}
|
||||
|
||||
function search(query, page) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
const hitsPerPage = 10
|
||||
|
||||
const params = {
|
||||
// typoTolerance: 'min',
|
||||
optionalFacetFilters: `concatenatedName:${concat(query)}`,
|
||||
facets: [ 'keywords' ],
|
||||
attributesToHighlight: null,
|
||||
attributesToRetrieve: [
|
||||
'description',
|
||||
'githubRepo',
|
||||
'keywords',
|
||||
'license',
|
||||
'name',
|
||||
'owner',
|
||||
'version'
|
||||
],
|
||||
// restrictSearchableAttributes: [
|
||||
// 'name',
|
||||
// 'description',
|
||||
// 'keywords'
|
||||
// ],
|
||||
hitsPerPage,
|
||||
page
|
||||
}
|
||||
|
||||
searchIndex.search(query, params, function (error, value) {
|
||||
if (error) {
|
||||
reject(error)
|
||||
} else {
|
||||
resolve(
|
||||
Promise.all(
|
||||
value.hits.map(enhanceHit)
|
||||
).then(function (hits) {
|
||||
hits.sort(byRelevanceDescending)
|
||||
|
||||
const totalHits = value.nbHits
|
||||
const totalPages = value.nbPages
|
||||
|
||||
return {
|
||||
query,
|
||||
page,
|
||||
hitsPerPage,
|
||||
totalHits,
|
||||
totalPages,
|
||||
hits
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = search
|
Loading…
Reference in New Issue