More work on search

This commit is contained in:
MICHAEL JACKSON 2017-09-13 09:30:49 -07:00
parent f4f0c59552
commit 8ed2296b2f
3 changed files with 95 additions and 69 deletions

View File

@ -1,83 +1,20 @@
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
})
}, function (error) {
console.error(error)
res.status(500).send({ error: 'There was an error executing the search' })
})
}
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' })
})
})

View File

@ -1,3 +1,4 @@
const semver = require('semver')
const assetPathsIndex = require('./assetPathsIndex')
function getAssetPaths(packageName, version) {

88
server/npm/search.js Normal file
View File

@ -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