From a594feada7921b9e9bd4e74e61b27ed9c829fbd9 Mon Sep 17 00:00:00 2001
From: joachimzeelmaekers <>
Date: Mon, 28 Jul 2025 11:39:55 +0200
Subject: [PATCH 1/2] chore: remove logs
---
api/controllers/SearchController.js | 1119 ++++++++++++++-------------
1 file changed, 593 insertions(+), 526 deletions(-)
diff --git a/api/controllers/SearchController.js b/api/controllers/SearchController.js
index 082c70dd..5980217b 100644
--- a/api/controllers/SearchController.js
+++ b/api/controllers/SearchController.js
@@ -4,60 +4,60 @@
* @description :: Server-side logic for searching
* @help :: See http://sailsjs.org/#!/documentation/concepts/Controllers
*/
-var Promise = require('bluebird');
-var _ = require('lodash');
-var striptags = require('striptags');
-var querystring = require('querystring');
-var numeral = require('numeral');
-
-var splitInPackageAndFunction = function(query) {
- return decodeURIComponent(query).split('::');
+var Promise = require("bluebird");
+var _ = require("lodash");
+var striptags = require("striptags");
+var querystring = require("querystring");
+var numeral = require("numeral");
+
+var splitInPackageAndFunction = function (query) {
+ return decodeURIComponent(query).split("::");
};
-var isInPackageSearch = function(query) {
+var isInPackageSearch = function (query) {
return splitInPackageAndFunction(query).length === 2;
};
module.exports = {
/**
- * @api {post} /quick_search Quick search
- * @apiName quick search
- * @apiGroup Search
- * @apiDescription Searches for the given keyword and gives top results for packages, functions and collaborators.
- *
- * @apiParam {String} token The token on which is searched
- *
- * @apiSuccess {Object[]} packages The packages related to the token.
- * @apiSuccess {String} packages.uri The link to the package.
- * @apiSuccess {String} packages.name The name of the package.
- * @apiSuccess {Object[]} topics The topics (i.e. functions) related to the token.
- * @apiSuccess {String} topics.uri The link to the topic.
- * @apiSuccess {String} topics.name The name of the topic.
- * @apiSuccess {String} topics.package_name The name of the package of the topic.
- * @apiSuccess {String} topics.package_version The version of the package of the topic.
- * @apiSuccess {Object[]} collaborators The collaborators matching the token.
- * @apiSuccess {String} collaborators.uri The link to the page of the collaborator.
- * @apiSuccess {String} collaborators.name The name of the collaborator.
- */
- quickSearch: function(req, res) {
+ * @api {post} /quick_search Quick search
+ * @apiName quick search
+ * @apiGroup Search
+ * @apiDescription Searches for the given keyword and gives top results for packages, functions and collaborators.
+ *
+ * @apiParam {String} token The token on which is searched
+ *
+ * @apiSuccess {Object[]} packages The packages related to the token.
+ * @apiSuccess {String} packages.uri The link to the package.
+ * @apiSuccess {String} packages.name The name of the package.
+ * @apiSuccess {Object[]} topics The topics (i.e. functions) related to the token.
+ * @apiSuccess {String} topics.uri The link to the topic.
+ * @apiSuccess {String} topics.name The name of the topic.
+ * @apiSuccess {String} topics.package_name The name of the package of the topic.
+ * @apiSuccess {String} topics.package_version The version of the package of the topic.
+ * @apiSuccess {Object[]} collaborators The collaborators matching the token.
+ * @apiSuccess {String} collaborators.uri The link to the page of the collaborator.
+ * @apiSuccess {String} collaborators.name The name of the collaborator.
+ */
+ quickSearch: function (req, res) {
var token = req.body.token;
var topic = token;
var packageMatchQuery = {
has_parent: {
- parent_type: 'package_version',
+ parent_type: "package_version",
query: { term: { latest_version: 1 } },
- inner_hits: { fields: ['package_name', 'version', 'latest_version'] }
- }
+ inner_hits: { fields: ["package_name", "version", "latest_version"] },
+ },
};
var packageMatchQueryForPackage = {
match_phrase_prefix: {
package_name: {
query: token,
- max_expansions: 20
- }
- }
+ max_expansions: 20,
+ },
+ },
};
if (isInPackageSearch(token)) {
@@ -65,213 +65,227 @@ module.exports = {
topic = packageAndFunction[1];
packageMatchQuery = {
has_parent: {
- parent_type: 'package_version',
+ parent_type: "package_version",
query: {
bool: {
must: [
{
- term: { latest_version: 1 }
+ term: { latest_version: 1 },
},
{
- term: { package_name: packageAndFunction[0] }
- }
- ]
- }
+ term: { package_name: packageAndFunction[0] },
+ },
+ ],
+ },
},
- inner_hits: { fields: ['package_name', 'version', 'latest_version'] }
- }
+ inner_hits: { fields: ["package_name", "version", "latest_version"] },
+ },
};
packageMatchQueryForPackage = {
match: {
package_name: {
- query: packageAndFunction[0]
- }
- }
+ query: packageAndFunction[0],
+ },
+ },
};
}
- var packages; var topics; var collaborators;
-
- var elastic = es.msearch({
- body: [
- { index: 'rdoc', type: 'package_version' },
- { query: {
- bool: {
- should: [
-
- {
- 'has_parent': {
- 'query': {
- 'function_score': {
- 'functions': [
- {
- 'filter': { 'missing': { 'field': 'part_of_r' } },
- 'field_value_factor': {
- 'field': 'last_month_downloads',
- 'modifier': 'log1p'
- }
- },
- {
- 'filter': { 'term': { 'part_of_r': 0 } },
- 'field_value_factor': {
- 'field': 'last_month_downloads',
- 'modifier': 'log1p'
- }
- },
- {
- 'filter': { 'term': { 'part_of_r': 1 } },
- 'field_value_factor': {
- 'field': 'part_of_r',
- 'modifier': 'log1p',
- 'factor': 3000
- }
- }
- ],
- 'boost_mode': 'multiply'
- }
- },
+ var packages;
+ var topics;
+ var collaborators;
- 'parent_type': 'package',
- 'score_mode': 'score'
- }
- }
- ],
- 'minimum_number_should_match': 2,
- filter: {
+ var elastic = es
+ .msearch({
+ body: [
+ { index: "rdoc", type: "package_version" },
+ {
+ query: {
bool: {
- must: [
- packageMatchQueryForPackage,
+ should: [
{
- term: { latest_version: 1 }
- }
- ]
- }
-
- }
- }
- },
- size: 5,
- fields: ['package_name', 'version']
- },
-
- { index: 'rdoc', type: 'topic' },
- { query: {
-
- bool: {
- should: [
- {
- 'multi_match': {
- 'query': topic,
- 'fields': [ 'aliases^2', 'name' ]
- }
- },
- {
- 'multi_match': {
- 'fields': ['aliases^2', 'name'],
- 'query': topic,
- boost: 0.2,
- 'type': 'phrase_prefix'
- }
- },
- {
- has_parent: {
- 'parent_type': 'package_version',
- 'score_mode': 'score',
- query: {
- 'has_parent': {
- 'query': {
- 'function_score': {
- 'functions': [
+ has_parent: {
+ query: {
+ function_score: {
+ functions: [
{
- 'filter': { 'missing': { 'field': 'part_of_r' } },
- 'field_value_factor': {
- 'field': 'last_month_downloads',
- 'modifier': 'log1p'
- }
+ filter: { missing: { field: "part_of_r" } },
+ field_value_factor: {
+ field: "last_month_downloads",
+ modifier: "log1p",
+ },
},
{
- 'filter': { 'term': { 'part_of_r': 0 } },
- 'field_value_factor': {
- 'field': 'last_month_downloads',
- 'modifier': 'log1p'
- }
+ filter: { term: { part_of_r: 0 } },
+ field_value_factor: {
+ field: "last_month_downloads",
+ modifier: "log1p",
+ },
},
{
- 'filter': { 'term': { 'part_of_r': 1 } },
- 'field_value_factor': {
- 'field': 'part_of_r',
- 'modifier': 'log1p',
- 'factor': 3000
- }
- }
+ filter: { term: { part_of_r: 1 } },
+ field_value_factor: {
+ field: "part_of_r",
+ modifier: "log1p",
+ factor: 3000,
+ },
+ },
],
- 'boost_mode': 'replace'
- }
+ boost_mode: "multiply",
+ },
},
- 'parent_type': 'package',
- 'score_mode': 'score'
- }
- }
- }
- }
- ],
- 'minimum_number_should_match': 1,
- filter: packageMatchQuery
- }
+ parent_type: "package",
+ score_mode: "score",
+ },
+ },
+ ],
+ minimum_number_should_match: 2,
+ filter: {
+ bool: {
+ must: [
+ packageMatchQueryForPackage,
+ {
+ term: { latest_version: 1 },
+ },
+ ],
+ },
+ },
+ },
+ },
+ size: 5,
+ fields: ["package_name", "version"],
+ },
- },
- size: 5,
- fields: ['name']
- }
+ { index: "rdoc", type: "topic" },
+ {
+ query: {
+ bool: {
+ should: [
+ {
+ multi_match: {
+ query: topic,
+ fields: ["aliases^2", "name"],
+ },
+ },
+ {
+ multi_match: {
+ fields: ["aliases^2", "name"],
+ query: topic,
+ boost: 0.2,
+ type: "phrase_prefix",
+ },
+ },
+ {
+ has_parent: {
+ parent_type: "package_version",
+ score_mode: "score",
+ query: {
+ has_parent: {
+ query: {
+ function_score: {
+ functions: [
+ {
+ filter: { missing: { field: "part_of_r" } },
+ field_value_factor: {
+ field: "last_month_downloads",
+ modifier: "log1p",
+ },
+ },
+ {
+ filter: { term: { part_of_r: 0 } },
+ field_value_factor: {
+ field: "last_month_downloads",
+ modifier: "log1p",
+ },
+ },
+ {
+ filter: { term: { part_of_r: 1 } },
+ field_value_factor: {
+ field: "part_of_r",
+ modifier: "log1p",
+ factor: 3000,
+ },
+ },
+ ],
+ boost_mode: "replace",
+ },
+ },
- ]}).then(function(response) {
+ parent_type: "package",
+ score_mode: "score",
+ },
+ },
+ },
+ },
+ ],
+ minimum_number_should_match: 1,
+ filter: packageMatchQuery,
+ },
+ },
+ size: 5,
+ fields: ["name"],
+ },
+ ],
+ })
+ .then(function (response) {
var packageResult = response.responses[0];
var topicResult = response.responses[1];
- packages = _.map(packageResult.hits.hits, function(hit) {
+ packages = _.map(packageResult.hits.hits, function (hit) {
var name = hit.fields.package_name[0];
var version = hit.fields.version[0];
- var uri = sails.getUrlFor({ target: 'PackageVersion.findByNameVersion' })
- .replace(':name', encodeURIComponent(name))
- .replace(':version', encodeURIComponent(version))
- .replace('/api/', '/');
- return { uri: uri, name: name };
+ var uri = sails
+ .getUrlFor({ target: "PackageVersion.findByNameVersion" })
+ .replace(":name", encodeURIComponent(name))
+ .replace(":version", encodeURIComponent(version))
+ .replace("/api/", "/");
+ return { uri: uri, name: name };
});
- topics = _.map(topicResult.hits.hits, function(hit) {
+ topics = _.map(topicResult.hits.hits, function (hit) {
var name = hit.fields.name[0];
var id = hit._id;
var inner_hit = hit.inner_hits.package_version.hits.hits[0];
var package_name = inner_hit.fields.package_name[0];
var version = inner_hit.fields.version[0];
- var uri = '/api/packages/:name/versions/:version/topics/:topic'
- .replace(':name', encodeURIComponent(package_name))
- .replace(':version', encodeURIComponent(version))
- .replace(':topic', encodeURIComponent(name))
- .replace('/api/', '/');
- return { uri: uri, name: name, package_name: package_name, package_version: version };
+ var uri = "/api/packages/:name/versions/:version/topics/:topic"
+ .replace(":name", encodeURIComponent(package_name))
+ .replace(":version", encodeURIComponent(version))
+ .replace(":topic", encodeURIComponent(name))
+ .replace("/api/", "/");
+ return {
+ uri: uri,
+ name: name,
+ package_name: package_name,
+ package_version: version,
+ };
});
});
- var coll = Collaborator.quickSearch(token).then(function(result) {
- collaborators = _.map(result, function(collaborator) {
- var uri = '/collaborators/name/' + encodeURIComponent(collaborator.name);
- return {uri: uri, name: collaborator.name};
+ var coll = Collaborator.quickSearch(token).then(function (result) {
+ collaborators = _.map(result, function (collaborator) {
+ var uri =
+ "/collaborators/name/" + encodeURIComponent(collaborator.name);
+ return { uri: uri, name: collaborator.name };
});
});
- Promise.all([elastic, coll]).then(function() {
- return res.json({packages: packages, topics: topics, collaborators: collaborators});
- })
- .catch(function(err) {
- return res.negotiate(err);
- });
+ Promise.all([elastic, coll])
+ .then(function () {
+ return res.json({
+ packages: packages,
+ topics: topics,
+ collaborators: collaborators,
+ });
+ })
+ .catch(function (err) {
+ return res.negotiate(err);
+ });
},
- keywordSearch: function(req, res) {
- var keyword = req.param('keyword');
- var page = parseInt(req.param('page')) || 1;
- var perPage = parseInt(req.param('perPage')) || 10;
+ keywordSearch: function (req, res) {
+ var keyword = req.param("keyword");
+ var page = parseInt(req.param("page")) || 1;
+ var perPage = parseInt(req.param("perPage")) || 10;
var offset = (page - 1) * perPage;
var nextPageQuery = _.clone(req.query);
nextPageQuery.page = page + 1;
@@ -279,419 +293,472 @@ module.exports = {
var prevPageQuery = _.clone(req.query);
prevPageQuery.page = page - 1;
- sails.log.info("keywordSearch()", JSON.stringify({
- headers: req.headers,
- wantsJson: req.wantsJSON,
- }));
-
es.search({
- index: 'rdoc',
+ index: "rdoc",
body: {
query: {
bool: {
filter: {
type: {
- value: 'topic'
- }
+ value: "topic",
+ },
},
must: [
{
term: {
- keywords: keyword
- }
+ keywords: keyword,
+ },
},
{
has_parent: {
- parent_type: 'package_version',
+ parent_type: "package_version",
query: {
term: {
- latest_version: 1
- }
+ latest_version: 1,
+ },
+ },
+ inner_hits: {
+ fields: ["package_name", "version", "latest_version"],
},
- inner_hits: { fields: ['package_name', 'version', 'latest_version'] }
- }
- }
- ]
- }
+ },
+ },
+ ],
+ },
},
highlight: {
- pre_tags: [''],
- post_tags: [''],
- 'fields': {
- 'keywords': {
+ pre_tags: [""],
+ post_tags: [""],
+ fields: {
+ keywords: {
highlight_query: {
term: {
- keywords: keyword
- }
- }
- }
-
- }
+ keywords: keyword,
+ },
+ },
+ },
+ },
},
from: offset,
size: perPage,
- fields: ['title', 'name', 'description', 'keywords']
- }
-
- }).then(function(response) {
- // return res.json(response);
- var hits = response.hits.hits.map(function(hit) {
- var fields = {};
- var highlight = hit.highlight;
- var inner_hits_fields = hit.inner_hits.package_version.hits.hits[0].fields;
-
- fields.package_name = inner_hits_fields.package_name[0];
- fields.version = inner_hits_fields.version[0];
- fields.name = hit.fields.name[0];
-
- highlight.title = hit.fields.title[0];
- highlight.description = hit.fields.description[0];
-
- return {
- fields: fields,
- type: hit._type,
- score: hit._score,
- highlight: hit.highlight
- };
- });
- return res.ok({
- total: numeral(response.hits.total).format('0,0'),
- hits: hits,
- perPage: perPage,
- currentPage: page,
- prevPageUrl: req.path + '?' + querystring.stringify(prevPageQuery),
- nextPageUrl: req.path + '?' + querystring.stringify(nextPageQuery),
- striptags: striptags,
- pageTitle: 'Search Results'
- }, 'search/keyword_result.ejs');
+ fields: ["title", "name", "description", "keywords"],
+ },
})
- .catch(function(err) {
- return res.negotiate(err);
- });
+ .then(function (response) {
+ // return res.json(response);
+ var hits = response.hits.hits.map(function (hit) {
+ var fields = {};
+ var highlight = hit.highlight;
+ var inner_hits_fields =
+ hit.inner_hits.package_version.hits.hits[0].fields;
+
+ fields.package_name = inner_hits_fields.package_name[0];
+ fields.version = inner_hits_fields.version[0];
+ fields.name = hit.fields.name[0];
+
+ highlight.title = hit.fields.title[0];
+ highlight.description = hit.fields.description[0];
+
+ return {
+ fields: fields,
+ type: hit._type,
+ score: hit._score,
+ highlight: hit.highlight,
+ };
+ });
+ return res.ok(
+ {
+ total: numeral(response.hits.total).format("0,0"),
+ hits: hits,
+ perPage: perPage,
+ currentPage: page,
+ prevPageUrl: req.path + "?" + querystring.stringify(prevPageQuery),
+ nextPageUrl: req.path + "?" + querystring.stringify(nextPageQuery),
+ striptags: striptags,
+ pageTitle: "Search Results",
+ },
+ "search/keyword_result.ejs"
+ );
+ })
+ .catch(function (err) {
+ return res.negotiate(err);
+ });
},
- packageSearch: function(req, res) {
- var query = req.param('q');
- var page = parseInt(req.param('page')) || 1;
- var perPage = parseInt(req.param('perPage')) || 15;
- var onlyLatestVersion = (parseInt(req.param('latest'))) === 1;
+ packageSearch: function (req, res) {
+ var query = req.param("q");
+ var page = parseInt(req.param("page")) || 1;
+ var perPage = parseInt(req.param("perPage")) || 15;
+ var onlyLatestVersion = parseInt(req.param("latest")) === 1;
var offset = (page - 1) * perPage;
var packageVersionFilter = [
{
type: {
- value: 'package_version'
- }
- }
+ value: "package_version",
+ },
+ },
];
if (onlyLatestVersion) {
packageVersionFilter.push({ term: { latest_version: 1 } });
}
- sails.log.info("packageSearch()", JSON.stringify({
- headers: req.headers,
- wantsJson: req.wantsJSON,
- }));
-
- return es.search({
- index: 'rdoc',
- body: {
- query: {
- bool: {
- filter: packageVersionFilter,
- should: [
- {
- multi_match: {
- query: query,
- type: 'best_fields',
- fields: ['package_name^6', 'title^4', 'maintainer.name^4', 'collaborators.name^3', 'description^3', 'license', 'url', 'copyright']
- }
- },
- {
- match_phrase_prefix: {
- 'package_name': {
- 'query': query,
- 'max_expansions': 20
- }
- }
- },
- {
- 'has_parent': {
- 'query': {
- 'function_score': {
- 'functions': [
- {
- 'filter': { 'missing': { 'field': 'part_of_r' } },
- 'field_value_factor': {
- 'field': 'last_month_downloads',
- 'modifier': 'log1p'
- }
- },
- {
- 'filter': { 'term': { 'part_of_r': 0 } },
- 'field_value_factor': {
- 'field': 'last_month_downloads',
- 'modifier': 'log1p'
- }
- },
- {
- 'filter': { 'term': { 'part_of_r': 1 } },
- 'field_value_factor': {
- 'field': 'part_of_r',
- 'modifier': 'log1p',
- 'factor': 3000
- }
- }
- ],
- 'boost_mode': 'replace'
- }
+ return es
+ .search({
+ index: "rdoc",
+ body: {
+ query: {
+ bool: {
+ filter: packageVersionFilter,
+ should: [
+ {
+ multi_match: {
+ query: query,
+ type: "best_fields",
+ fields: [
+ "package_name^6",
+ "title^4",
+ "maintainer.name^4",
+ "collaborators.name^3",
+ "description^3",
+ "license",
+ "url",
+ "copyright",
+ ],
+ },
+ },
+ {
+ match_phrase_prefix: {
+ package_name: {
+ query: query,
+ max_expansions: 20,
+ },
},
+ },
+ {
+ has_parent: {
+ query: {
+ function_score: {
+ functions: [
+ {
+ filter: { missing: { field: "part_of_r" } },
+ field_value_factor: {
+ field: "last_month_downloads",
+ modifier: "log1p",
+ },
+ },
+ {
+ filter: { term: { part_of_r: 0 } },
+ field_value_factor: {
+ field: "last_month_downloads",
+ modifier: "log1p",
+ },
+ },
+ {
+ filter: { term: { part_of_r: 1 } },
+ field_value_factor: {
+ field: "part_of_r",
+ modifier: "log1p",
+ factor: 3000,
+ },
+ },
+ ],
+ boost_mode: "replace",
+ },
+ },
- 'parent_type': 'package',
- 'score_mode': 'score'
- }
- }
- ],
- minimum_should_match: 1
- }
- },
- highlight: {
- pre_tags: [''],
- post_tags: [''],
- 'require_field_match': false,
- 'fields': {
- 'description': {
- 'number_of_fragments': 0,
- highlight_query: {
- match: { description: query }
- }
- }
- }
+ parent_type: "package",
+ score_mode: "score",
+ },
+ },
+ ],
+ minimum_should_match: 1,
+ },
+ },
+ highlight: {
+ pre_tags: [""],
+ post_tags: [""],
+ require_field_match: false,
+ fields: {
+ description: {
+ number_of_fragments: 0,
+ highlight_query: {
+ match: { description: query },
+ },
+ },
+ },
+ },
+ from: offset,
+ size: perPage,
+ fields: ["package_name", "version", "description", "maintainer.name"],
},
- from: offset,
- size: perPage,
- fields: ['package_name', 'version', 'description', 'maintainer.name']
- }
- }).then(function(result) {
- var packages = [];
- result.hits.hits.forEach(function(hit) {
- var fields = {};
- fields.package_name = hit.fields.package_name[0];
- fields.version = hit.fields.version[0];
- fields.maintainer = hit.fields['maintainer.name'];
- var highlights = _.mapValues(hit.highlight, function(highlight) {
- return striptags(highlight.toString(), '');
+ })
+ .then(function (result) {
+ var packages = [];
+ result.hits.hits.forEach(function (hit) {
+ var fields = {};
+ fields.package_name = hit.fields.package_name[0];
+ fields.version = hit.fields.version[0];
+ fields.maintainer = hit.fields["maintainer.name"];
+ var highlights = _.mapValues(hit.highlight, function (highlight) {
+ return striptags(highlight.toString(), "");
+ });
+
+ var description = highlights.description || hit.fields.description[0];
+
+ packages.push({
+ description: description,
+ fields: fields,
+ score: hit._score,
+ });
});
-
- var description = highlights.description || hit.fields.description[0];
-
- packages.push({
- description: description,
- fields: fields,
- score: hit._score
+ res.locals.layout = null;
+ if (req.headers.accept === "application/json") {
+ return res.json({
+ packages: packages,
+ hits: result.hits.total,
+ });
+ }
+ return res.view("search/package_results.ejs", {
+ data: {
+ packages: packages,
+ hits: numeral(result.hits.total).format("0,0"),
+ },
});
+ })
+ .catch(function (err) {
+ return res.negotiate(err);
});
- res.locals.layout = null;
- if (req.headers.accept === 'application/json') {
- return res.json({
- packages: packages, hits: result.hits.total
- });
- }
- return res.view('search/package_results.ejs', { data: {packages: packages, hits: numeral(result.hits.total).format('0,0')}});
- }).catch(function(err) {
- return res.negotiate(err);
- });
},
- functionSearch: function(req, res) {
- var query = req.param('q');
- var package = req.param('package');
- var page = parseInt(req.param('page')) || 1;
- var perPage = parseInt(req.param('perPage')) || 15;
- var onlyLatestVersion = (parseInt(req.param('latest'))) === 1;
+ functionSearch: function (req, res) {
+ var query = req.param("q");
+ var package = req.param("package");
+ var page = parseInt(req.param("page")) || 1;
+ var perPage = parseInt(req.param("perPage")) || 15;
+ var onlyLatestVersion = parseInt(req.param("latest")) === 1;
var offset = (page - 1) * perPage;
var searchTopicQuery = {
multi_match: {
query: query,
- type: 'best_fields',
+ type: "best_fields",
boost: 1,
fields: [
- 'aliases^6',
- 'name^2',
- 'title^2', 'description', 'keywords^2',
- 'arguments.name', 'arguments.description',
- 'details', 'value',
- 'note', 'author']
- }
+ "aliases^6",
+ "name^2",
+ "title^2",
+ "description",
+ "keywords^2",
+ "arguments.name",
+ "arguments.description",
+ "details",
+ "value",
+ "note",
+ "author",
+ ],
+ },
};
var prefixQuery = {
- 'multi_match': {
+ multi_match: {
boost: 0.2,
- 'fields': ['aliases^2', 'name'],
- 'query': query,
- 'type': 'phrase_prefix'
- }
+ fields: ["aliases^2", "name"],
+ query: query,
+ type: "phrase_prefix",
+ },
};
var topicFilter = [
{
type: {
- value: 'topic'
- }
- }
+ value: "topic",
+ },
+ },
];
var packageMatchQuery;
if (package === undefined) {
packageMatchQuery = {
has_parent: {
- parent_type: 'package_version'
- }
+ parent_type: "package_version",
+ },
};
if (onlyLatestVersion) {
- packageMatchQuery.has_parent.query = { term: { latest_version: 1 } };
+ packageMatchQuery.has_parent.query = { term: { latest_version: 1 } };
topicFilter.push(packageMatchQuery);
}
- } else {
+ } else {
packageMatchQuery = {
has_parent: {
- parent_type: 'package_version',
+ parent_type: "package_version",
query: {
- 'bool': {
- 'must': [
+ bool: {
+ must: [
{
- term: { package_name: package }
- }
- ]
- }
- }
- }
+ term: { package_name: package },
+ },
+ ],
+ },
+ },
+ },
};
- if (onlyLatestVersion) {packageMatchQuery.has_parent.query.bool.must.push({term: { latest_version: 1 }});}
+ if (onlyLatestVersion) {
+ packageMatchQuery.has_parent.query.bool.must.push({
+ term: { latest_version: 1 },
+ });
+ }
topicFilter.push(packageMatchQuery);
}
- return es.search({
- index: 'rdoc',
- body: {
- query: {
- bool: {
- should: [
- {
- bool: {
- filter: topicFilter,
- should: [
- searchTopicQuery,
- prefixQuery,
- {
- has_parent: {
- parent_type: 'package_version',
- score_mode: 'score',
-
- query: {
- 'has_parent': {
- 'parent_type': 'package',
- 'score_mode': 'score',
- 'query': {
- 'function_score': {
- 'functions': [
- {
- 'filter': { 'missing': { 'field': 'part_of_r' } },
- 'field_value_factor': {
- 'field': 'last_month_downloads',
- 'modifier': 'log1p'
- }
- },
- {
- 'filter': { 'term': { 'part_of_r': 0 } },
- 'field_value_factor': {
- 'field': 'last_month_downloads',
- 'modifier': 'log1p'
- }
- },
- {
- 'filter': { 'term': { 'part_of_r': 1 } },
- 'field_value_factor': {
- 'field': 'part_of_r',
- 'modifier': 'log1p',
- 'factor': 3000
- }
- }
- ],
- 'boost_mode': 'replace'
- }
- }
- }
+ return es
+ .search({
+ index: "rdoc",
+ body: {
+ query: {
+ bool: {
+ should: [
+ {
+ bool: {
+ filter: topicFilter,
+ should: [
+ searchTopicQuery,
+ prefixQuery,
+ {
+ has_parent: {
+ parent_type: "package_version",
+ score_mode: "score",
+
+ query: {
+ has_parent: {
+ parent_type: "package",
+ score_mode: "score",
+ query: {
+ function_score: {
+ functions: [
+ {
+ filter: {
+ missing: { field: "part_of_r" },
+ },
+ field_value_factor: {
+ field: "last_month_downloads",
+ modifier: "log1p",
+ },
+ },
+ {
+ filter: { term: { part_of_r: 0 } },
+ field_value_factor: {
+ field: "last_month_downloads",
+ modifier: "log1p",
+ },
+ },
+ {
+ filter: { term: { part_of_r: 1 } },
+ field_value_factor: {
+ field: "part_of_r",
+ modifier: "log1p",
+ factor: 3000,
+ },
+ },
+ ],
+ boost_mode: "replace",
+ },
+ },
+ },
+ },
+ inner_hits: {
+ fields: [
+ "package_name",
+ "version",
+ "latest_version",
+ "maintainer.name",
+ ],
+ },
},
- inner_hits: { fields: ['package_name', 'version', 'latest_version', 'maintainer.name'] }
- }
- }
- ],
- minimum_should_match: 1
- }
- }],
- minimum_should_match: 1
- }
- },
- highlight: {
- pre_tags: [''],
- post_tags: [''],
- 'fields': {
- 'description': {
- 'number_of_fragments': 0,
- highlight_query: searchTopicQuery
+ },
+ ],
+ minimum_should_match: 1,
+ },
+ },
+ ],
+ minimum_should_match: 1,
+ },
+ },
+ highlight: {
+ pre_tags: [""],
+ post_tags: [""],
+ fields: {
+ description: {
+ number_of_fragments: 0,
+ highlight_query: searchTopicQuery,
+ },
+ title: {
+ number_of_fragments: 0,
+ highlight_query: searchTopicQuery,
+ },
},
- 'title': {
- 'number_of_fragments': 0,
- highlight_query: searchTopicQuery}
- }
+ },
+ from: offset,
+ size: perPage,
+ fields: [
+ "package_name",
+ "version",
+ "name",
+ "maintainer.name",
+ "description",
+ "title",
+ ],
},
- from: offset,
- size: perPage,
- fields: ['package_name', 'version', 'name', 'maintainer.name', 'description', 'title']
- }
- }).then(function(result) {
- var functions = [];
- result.hits.hits.forEach(function(hit) {
- var fields = {};
- var inner_hits_fields = hit.inner_hits.package_version.hits.hits[0].fields;
- fields.package_name = inner_hits_fields.package_name[0];
- fields.version = inner_hits_fields.version[0];
- fields.name = hit.fields.name[0];
- fields.maintainer = (inner_hits_fields && inner_hits_fields['maintainer.name'])
- ? inner_hits_fields['maintainer.name'][0]
- : undefined;
-
- var highlights = _.mapValues(hit.highlight, function(highlight) {
- return striptags(highlight.toString(), '');
+ })
+ .then(function (result) {
+ var functions = [];
+ result.hits.hits.forEach(function (hit) {
+ var fields = {};
+ var inner_hits_fields =
+ hit.inner_hits.package_version.hits.hits[0].fields;
+ fields.package_name = inner_hits_fields.package_name[0];
+ fields.version = inner_hits_fields.version[0];
+ fields.name = hit.fields.name[0];
+ fields.maintainer =
+ inner_hits_fields && inner_hits_fields["maintainer.name"]
+ ? inner_hits_fields["maintainer.name"][0]
+ : undefined;
+
+ var highlights = _.mapValues(hit.highlight, function (highlight) {
+ return striptags(highlight.toString(), "");
+ });
+
+ var description = highlights.description || hit.fields.description[0];
+ var title = highlights.title || hit.fields.title[0];
+
+ functions.push({
+ fields: fields,
+ score: hit._score,
+ description: description,
+ title: title,
+ });
});
-
- var description = highlights.description || hit.fields.description[0];
- var title = highlights.title || hit.fields.title[0];
-
- functions.push({
- fields: fields,
- score: hit._score,
- description: description,
- title: title
+ res.locals.layout = null;
+ if (req.headers.accept === "application/json") {
+ return res.json({
+ functions: functions,
+ hits: result.hits.total,
+ });
+ }
+ return res.view("search/function_results.ejs", {
+ data: {
+ functions: functions,
+ hits: numeral(result.hits.total).format("0,0"),
+ },
});
+ })
+ .catch(function (err) {
+ return res.negotiate(err);
});
- res.locals.layout = null;
- if (req.headers.accept === 'application/json') {
- return res.json({
- functions: functions, hits: result.hits.total
- });
- }
- return res.view('search/function_results.ejs', {data: {functions: functions, hits: numeral(result.hits.total).format('0,0')}});
- }).catch(function(err) {
- return res.negotiate(err);
- });
},
-
- fullSearch: function(req, res) {
- return res.redirect(302, "https://rdocumentation.org/search?q=" + req.param('q'));
- }
-
+ fullSearch: function (req, res) {
+ return res.redirect(
+ 302,
+ "https://rdocumentation.org/search?q=" + req.param("q")
+ );
+ },
};
From 271e96b5d9cf6aad929982f121d6c0d5a6591970 Mon Sep 17 00:00:00 2001
From: joachimzeelmaekers <>
Date: Mon, 28 Jul 2025 11:40:33 +0200
Subject: [PATCH 2/2] chore: undo
---
api/controllers/SearchController.js | 1109 +++++++++++++--------------
1 file changed, 516 insertions(+), 593 deletions(-)
diff --git a/api/controllers/SearchController.js b/api/controllers/SearchController.js
index 5980217b..01ad0bc3 100644
--- a/api/controllers/SearchController.js
+++ b/api/controllers/SearchController.js
@@ -4,60 +4,60 @@
* @description :: Server-side logic for searching
* @help :: See http://sailsjs.org/#!/documentation/concepts/Controllers
*/
-var Promise = require("bluebird");
-var _ = require("lodash");
-var striptags = require("striptags");
-var querystring = require("querystring");
-var numeral = require("numeral");
-
-var splitInPackageAndFunction = function (query) {
- return decodeURIComponent(query).split("::");
+var Promise = require('bluebird');
+var _ = require('lodash');
+var striptags = require('striptags');
+var querystring = require('querystring');
+var numeral = require('numeral');
+
+var splitInPackageAndFunction = function(query) {
+ return decodeURIComponent(query).split('::');
};
-var isInPackageSearch = function (query) {
+var isInPackageSearch = function(query) {
return splitInPackageAndFunction(query).length === 2;
};
module.exports = {
/**
- * @api {post} /quick_search Quick search
- * @apiName quick search
- * @apiGroup Search
- * @apiDescription Searches for the given keyword and gives top results for packages, functions and collaborators.
- *
- * @apiParam {String} token The token on which is searched
- *
- * @apiSuccess {Object[]} packages The packages related to the token.
- * @apiSuccess {String} packages.uri The link to the package.
- * @apiSuccess {String} packages.name The name of the package.
- * @apiSuccess {Object[]} topics The topics (i.e. functions) related to the token.
- * @apiSuccess {String} topics.uri The link to the topic.
- * @apiSuccess {String} topics.name The name of the topic.
- * @apiSuccess {String} topics.package_name The name of the package of the topic.
- * @apiSuccess {String} topics.package_version The version of the package of the topic.
- * @apiSuccess {Object[]} collaborators The collaborators matching the token.
- * @apiSuccess {String} collaborators.uri The link to the page of the collaborator.
- * @apiSuccess {String} collaborators.name The name of the collaborator.
- */
- quickSearch: function (req, res) {
+ * @api {post} /quick_search Quick search
+ * @apiName quick search
+ * @apiGroup Search
+ * @apiDescription Searches for the given keyword and gives top results for packages, functions and collaborators.
+ *
+ * @apiParam {String} token The token on which is searched
+ *
+ * @apiSuccess {Object[]} packages The packages related to the token.
+ * @apiSuccess {String} packages.uri The link to the package.
+ * @apiSuccess {String} packages.name The name of the package.
+ * @apiSuccess {Object[]} topics The topics (i.e. functions) related to the token.
+ * @apiSuccess {String} topics.uri The link to the topic.
+ * @apiSuccess {String} topics.name The name of the topic.
+ * @apiSuccess {String} topics.package_name The name of the package of the topic.
+ * @apiSuccess {String} topics.package_version The version of the package of the topic.
+ * @apiSuccess {Object[]} collaborators The collaborators matching the token.
+ * @apiSuccess {String} collaborators.uri The link to the page of the collaborator.
+ * @apiSuccess {String} collaborators.name The name of the collaborator.
+ */
+ quickSearch: function(req, res) {
var token = req.body.token;
var topic = token;
var packageMatchQuery = {
has_parent: {
- parent_type: "package_version",
+ parent_type: 'package_version',
query: { term: { latest_version: 1 } },
- inner_hits: { fields: ["package_name", "version", "latest_version"] },
- },
+ inner_hits: { fields: ['package_name', 'version', 'latest_version'] }
+ }
};
var packageMatchQueryForPackage = {
match_phrase_prefix: {
package_name: {
query: token,
- max_expansions: 20,
- },
- },
+ max_expansions: 20
+ }
+ }
};
if (isInPackageSearch(token)) {
@@ -65,227 +65,213 @@ module.exports = {
topic = packageAndFunction[1];
packageMatchQuery = {
has_parent: {
- parent_type: "package_version",
+ parent_type: 'package_version',
query: {
bool: {
must: [
{
- term: { latest_version: 1 },
+ term: { latest_version: 1 }
},
{
- term: { package_name: packageAndFunction[0] },
- },
- ],
- },
+ term: { package_name: packageAndFunction[0] }
+ }
+ ]
+ }
},
- inner_hits: { fields: ["package_name", "version", "latest_version"] },
- },
+ inner_hits: { fields: ['package_name', 'version', 'latest_version'] }
+ }
};
packageMatchQueryForPackage = {
match: {
package_name: {
- query: packageAndFunction[0],
- },
- },
+ query: packageAndFunction[0]
+ }
+ }
};
}
- var packages;
- var topics;
- var collaborators;
+ var packages; var topics; var collaborators;
+
+ var elastic = es.msearch({
+ body: [
+ { index: 'rdoc', type: 'package_version' },
+ { query: {
+ bool: {
+ should: [
+
+ {
+ 'has_parent': {
+ 'query': {
+ 'function_score': {
+ 'functions': [
+ {
+ 'filter': { 'missing': { 'field': 'part_of_r' } },
+ 'field_value_factor': {
+ 'field': 'last_month_downloads',
+ 'modifier': 'log1p'
+ }
+ },
+ {
+ 'filter': { 'term': { 'part_of_r': 0 } },
+ 'field_value_factor': {
+ 'field': 'last_month_downloads',
+ 'modifier': 'log1p'
+ }
+ },
+ {
+ 'filter': { 'term': { 'part_of_r': 1 } },
+ 'field_value_factor': {
+ 'field': 'part_of_r',
+ 'modifier': 'log1p',
+ 'factor': 3000
+ }
+ }
+ ],
+ 'boost_mode': 'multiply'
+ }
+ },
- var elastic = es
- .msearch({
- body: [
- { index: "rdoc", type: "package_version" },
- {
- query: {
+ 'parent_type': 'package',
+ 'score_mode': 'score'
+ }
+ }
+ ],
+ 'minimum_number_should_match': 2,
+ filter: {
bool: {
- should: [
+ must: [
+ packageMatchQueryForPackage,
{
- has_parent: {
- query: {
- function_score: {
- functions: [
+ term: { latest_version: 1 }
+ }
+ ]
+ }
+
+ }
+ }
+ },
+ size: 5,
+ fields: ['package_name', 'version']
+ },
+
+ { index: 'rdoc', type: 'topic' },
+ { query: {
+
+ bool: {
+ should: [
+ {
+ 'multi_match': {
+ 'query': topic,
+ 'fields': [ 'aliases^2', 'name' ]
+ }
+ },
+ {
+ 'multi_match': {
+ 'fields': ['aliases^2', 'name'],
+ 'query': topic,
+ boost: 0.2,
+ 'type': 'phrase_prefix'
+ }
+ },
+ {
+ has_parent: {
+ 'parent_type': 'package_version',
+ 'score_mode': 'score',
+ query: {
+ 'has_parent': {
+ 'query': {
+ 'function_score': {
+ 'functions': [
{
- filter: { missing: { field: "part_of_r" } },
- field_value_factor: {
- field: "last_month_downloads",
- modifier: "log1p",
- },
+ 'filter': { 'missing': { 'field': 'part_of_r' } },
+ 'field_value_factor': {
+ 'field': 'last_month_downloads',
+ 'modifier': 'log1p'
+ }
},
{
- filter: { term: { part_of_r: 0 } },
- field_value_factor: {
- field: "last_month_downloads",
- modifier: "log1p",
- },
+ 'filter': { 'term': { 'part_of_r': 0 } },
+ 'field_value_factor': {
+ 'field': 'last_month_downloads',
+ 'modifier': 'log1p'
+ }
},
{
- filter: { term: { part_of_r: 1 } },
- field_value_factor: {
- field: "part_of_r",
- modifier: "log1p",
- factor: 3000,
- },
- },
+ 'filter': { 'term': { 'part_of_r': 1 } },
+ 'field_value_factor': {
+ 'field': 'part_of_r',
+ 'modifier': 'log1p',
+ 'factor': 3000
+ }
+ }
],
- boost_mode: "multiply",
- },
+ 'boost_mode': 'replace'
+ }
},
- parent_type: "package",
- score_mode: "score",
- },
- },
- ],
- minimum_number_should_match: 2,
- filter: {
- bool: {
- must: [
- packageMatchQueryForPackage,
- {
- term: { latest_version: 1 },
- },
- ],
- },
- },
- },
- },
- size: 5,
- fields: ["package_name", "version"],
- },
+ 'parent_type': 'package',
+ 'score_mode': 'score'
+ }
+ }
+ }
+ }
+ ],
+ 'minimum_number_should_match': 1,
+ filter: packageMatchQuery
+ }
- { index: "rdoc", type: "topic" },
- {
- query: {
- bool: {
- should: [
- {
- multi_match: {
- query: topic,
- fields: ["aliases^2", "name"],
- },
- },
- {
- multi_match: {
- fields: ["aliases^2", "name"],
- query: topic,
- boost: 0.2,
- type: "phrase_prefix",
- },
- },
- {
- has_parent: {
- parent_type: "package_version",
- score_mode: "score",
- query: {
- has_parent: {
- query: {
- function_score: {
- functions: [
- {
- filter: { missing: { field: "part_of_r" } },
- field_value_factor: {
- field: "last_month_downloads",
- modifier: "log1p",
- },
- },
- {
- filter: { term: { part_of_r: 0 } },
- field_value_factor: {
- field: "last_month_downloads",
- modifier: "log1p",
- },
- },
- {
- filter: { term: { part_of_r: 1 } },
- field_value_factor: {
- field: "part_of_r",
- modifier: "log1p",
- factor: 3000,
- },
- },
- ],
- boost_mode: "replace",
- },
- },
+ },
+ size: 5,
+ fields: ['name']
+ }
- parent_type: "package",
- score_mode: "score",
- },
- },
- },
- },
- ],
- minimum_number_should_match: 1,
- filter: packageMatchQuery,
- },
- },
- size: 5,
- fields: ["name"],
- },
- ],
- })
- .then(function (response) {
+ ]}).then(function(response) {
var packageResult = response.responses[0];
var topicResult = response.responses[1];
- packages = _.map(packageResult.hits.hits, function (hit) {
+ packages = _.map(packageResult.hits.hits, function(hit) {
var name = hit.fields.package_name[0];
var version = hit.fields.version[0];
- var uri = sails
- .getUrlFor({ target: "PackageVersion.findByNameVersion" })
- .replace(":name", encodeURIComponent(name))
- .replace(":version", encodeURIComponent(version))
- .replace("/api/", "/");
- return { uri: uri, name: name };
+ var uri = sails.getUrlFor({ target: 'PackageVersion.findByNameVersion' })
+ .replace(':name', encodeURIComponent(name))
+ .replace(':version', encodeURIComponent(version))
+ .replace('/api/', '/');
+ return { uri: uri, name: name };
});
- topics = _.map(topicResult.hits.hits, function (hit) {
+ topics = _.map(topicResult.hits.hits, function(hit) {
var name = hit.fields.name[0];
var id = hit._id;
var inner_hit = hit.inner_hits.package_version.hits.hits[0];
var package_name = inner_hit.fields.package_name[0];
var version = inner_hit.fields.version[0];
- var uri = "/api/packages/:name/versions/:version/topics/:topic"
- .replace(":name", encodeURIComponent(package_name))
- .replace(":version", encodeURIComponent(version))
- .replace(":topic", encodeURIComponent(name))
- .replace("/api/", "/");
- return {
- uri: uri,
- name: name,
- package_name: package_name,
- package_version: version,
- };
+ var uri = '/api/packages/:name/versions/:version/topics/:topic'
+ .replace(':name', encodeURIComponent(package_name))
+ .replace(':version', encodeURIComponent(version))
+ .replace(':topic', encodeURIComponent(name))
+ .replace('/api/', '/');
+ return { uri: uri, name: name, package_name: package_name, package_version: version };
});
});
- var coll = Collaborator.quickSearch(token).then(function (result) {
- collaborators = _.map(result, function (collaborator) {
- var uri =
- "/collaborators/name/" + encodeURIComponent(collaborator.name);
- return { uri: uri, name: collaborator.name };
+ var coll = Collaborator.quickSearch(token).then(function(result) {
+ collaborators = _.map(result, function(collaborator) {
+ var uri = '/collaborators/name/' + encodeURIComponent(collaborator.name);
+ return {uri: uri, name: collaborator.name};
});
});
- Promise.all([elastic, coll])
- .then(function () {
- return res.json({
- packages: packages,
- topics: topics,
- collaborators: collaborators,
- });
- })
- .catch(function (err) {
- return res.negotiate(err);
- });
+ Promise.all([elastic, coll]).then(function() {
+ return res.json({packages: packages, topics: topics, collaborators: collaborators});
+ })
+ .catch(function(err) {
+ return res.negotiate(err);
+ });
},
- keywordSearch: function (req, res) {
- var keyword = req.param("keyword");
- var page = parseInt(req.param("page")) || 1;
- var perPage = parseInt(req.param("perPage")) || 10;
+ keywordSearch: function(req, res) {
+ var keyword = req.param('keyword');
+ var page = parseInt(req.param('page')) || 1;
+ var perPage = parseInt(req.param('perPage')) || 10;
var offset = (page - 1) * perPage;
var nextPageQuery = _.clone(req.query);
nextPageQuery.page = page + 1;
@@ -294,471 +280,408 @@ module.exports = {
prevPageQuery.page = page - 1;
es.search({
- index: "rdoc",
+ index: 'rdoc',
body: {
query: {
bool: {
filter: {
type: {
- value: "topic",
- },
+ value: 'topic'
+ }
},
must: [
{
term: {
- keywords: keyword,
- },
+ keywords: keyword
+ }
},
{
has_parent: {
- parent_type: "package_version",
+ parent_type: 'package_version',
query: {
term: {
- latest_version: 1,
- },
+ latest_version: 1
+ }
},
- inner_hits: {
- fields: ["package_name", "version", "latest_version"],
- },
- },
- },
- ],
- },
+ inner_hits: { fields: ['package_name', 'version', 'latest_version'] }
+ }
+ }
+ ]
+ }
},
highlight: {
- pre_tags: [""],
- post_tags: [""],
- fields: {
- keywords: {
+ pre_tags: [''],
+ post_tags: [''],
+ 'fields': {
+ 'keywords': {
highlight_query: {
term: {
- keywords: keyword,
- },
- },
- },
- },
+ keywords: keyword
+ }
+ }
+ }
+
+ }
},
from: offset,
size: perPage,
- fields: ["title", "name", "description", "keywords"],
- },
- })
- .then(function (response) {
- // return res.json(response);
- var hits = response.hits.hits.map(function (hit) {
- var fields = {};
- var highlight = hit.highlight;
- var inner_hits_fields =
- hit.inner_hits.package_version.hits.hits[0].fields;
-
- fields.package_name = inner_hits_fields.package_name[0];
- fields.version = inner_hits_fields.version[0];
- fields.name = hit.fields.name[0];
-
- highlight.title = hit.fields.title[0];
- highlight.description = hit.fields.description[0];
-
- return {
- fields: fields,
- type: hit._type,
- score: hit._score,
- highlight: hit.highlight,
- };
- });
- return res.ok(
- {
- total: numeral(response.hits.total).format("0,0"),
- hits: hits,
- perPage: perPage,
- currentPage: page,
- prevPageUrl: req.path + "?" + querystring.stringify(prevPageQuery),
- nextPageUrl: req.path + "?" + querystring.stringify(nextPageQuery),
- striptags: striptags,
- pageTitle: "Search Results",
- },
- "search/keyword_result.ejs"
- );
- })
- .catch(function (err) {
- return res.negotiate(err);
+ fields: ['title', 'name', 'description', 'keywords']
+ }
+
+ }).then(function(response) {
+ // return res.json(response);
+ var hits = response.hits.hits.map(function(hit) {
+ var fields = {};
+ var highlight = hit.highlight;
+ var inner_hits_fields = hit.inner_hits.package_version.hits.hits[0].fields;
+
+ fields.package_name = inner_hits_fields.package_name[0];
+ fields.version = inner_hits_fields.version[0];
+ fields.name = hit.fields.name[0];
+
+ highlight.title = hit.fields.title[0];
+ highlight.description = hit.fields.description[0];
+
+ return {
+ fields: fields,
+ type: hit._type,
+ score: hit._score,
+ highlight: hit.highlight
+ };
});
+ return res.ok({
+ total: numeral(response.hits.total).format('0,0'),
+ hits: hits,
+ perPage: perPage,
+ currentPage: page,
+ prevPageUrl: req.path + '?' + querystring.stringify(prevPageQuery),
+ nextPageUrl: req.path + '?' + querystring.stringify(nextPageQuery),
+ striptags: striptags,
+ pageTitle: 'Search Results'
+ }, 'search/keyword_result.ejs');
+ })
+ .catch(function(err) {
+ return res.negotiate(err);
+ });
},
- packageSearch: function (req, res) {
- var query = req.param("q");
- var page = parseInt(req.param("page")) || 1;
- var perPage = parseInt(req.param("perPage")) || 15;
- var onlyLatestVersion = parseInt(req.param("latest")) === 1;
+ packageSearch: function(req, res) {
+ var query = req.param('q');
+ var page = parseInt(req.param('page')) || 1;
+ var perPage = parseInt(req.param('perPage')) || 15;
+ var onlyLatestVersion = (parseInt(req.param('latest'))) === 1;
var offset = (page - 1) * perPage;
var packageVersionFilter = [
{
type: {
- value: "package_version",
- },
- },
+ value: 'package_version'
+ }
+ }
];
if (onlyLatestVersion) {
packageVersionFilter.push({ term: { latest_version: 1 } });
}
- return es
- .search({
- index: "rdoc",
- body: {
- query: {
- bool: {
- filter: packageVersionFilter,
- should: [
- {
- multi_match: {
- query: query,
- type: "best_fields",
- fields: [
- "package_name^6",
- "title^4",
- "maintainer.name^4",
- "collaborators.name^3",
- "description^3",
- "license",
- "url",
- "copyright",
- ],
- },
- },
- {
- match_phrase_prefix: {
- package_name: {
- query: query,
- max_expansions: 20,
- },
+ return es.search({
+ index: 'rdoc',
+ body: {
+ query: {
+ bool: {
+ filter: packageVersionFilter,
+ should: [
+ {
+ multi_match: {
+ query: query,
+ type: 'best_fields',
+ fields: ['package_name^6', 'title^4', 'maintainer.name^4', 'collaborators.name^3', 'description^3', 'license', 'url', 'copyright']
+ }
+ },
+ {
+ match_phrase_prefix: {
+ 'package_name': {
+ 'query': query,
+ 'max_expansions': 20
+ }
+ }
+ },
+ {
+ 'has_parent': {
+ 'query': {
+ 'function_score': {
+ 'functions': [
+ {
+ 'filter': { 'missing': { 'field': 'part_of_r' } },
+ 'field_value_factor': {
+ 'field': 'last_month_downloads',
+ 'modifier': 'log1p'
+ }
+ },
+ {
+ 'filter': { 'term': { 'part_of_r': 0 } },
+ 'field_value_factor': {
+ 'field': 'last_month_downloads',
+ 'modifier': 'log1p'
+ }
+ },
+ {
+ 'filter': { 'term': { 'part_of_r': 1 } },
+ 'field_value_factor': {
+ 'field': 'part_of_r',
+ 'modifier': 'log1p',
+ 'factor': 3000
+ }
+ }
+ ],
+ 'boost_mode': 'replace'
+ }
},
- },
- {
- has_parent: {
- query: {
- function_score: {
- functions: [
- {
- filter: { missing: { field: "part_of_r" } },
- field_value_factor: {
- field: "last_month_downloads",
- modifier: "log1p",
- },
- },
- {
- filter: { term: { part_of_r: 0 } },
- field_value_factor: {
- field: "last_month_downloads",
- modifier: "log1p",
- },
- },
- {
- filter: { term: { part_of_r: 1 } },
- field_value_factor: {
- field: "part_of_r",
- modifier: "log1p",
- factor: 3000,
- },
- },
- ],
- boost_mode: "replace",
- },
- },
- parent_type: "package",
- score_mode: "score",
- },
- },
- ],
- minimum_should_match: 1,
- },
- },
- highlight: {
- pre_tags: [""],
- post_tags: [""],
- require_field_match: false,
- fields: {
- description: {
- number_of_fragments: 0,
- highlight_query: {
- match: { description: query },
- },
- },
- },
- },
- from: offset,
- size: perPage,
- fields: ["package_name", "version", "description", "maintainer.name"],
+ 'parent_type': 'package',
+ 'score_mode': 'score'
+ }
+ }
+ ],
+ minimum_should_match: 1
+ }
+ },
+ highlight: {
+ pre_tags: [''],
+ post_tags: [''],
+ 'require_field_match': false,
+ 'fields': {
+ 'description': {
+ 'number_of_fragments': 0,
+ highlight_query: {
+ match: { description: query }
+ }
+ }
+ }
},
- })
- .then(function (result) {
- var packages = [];
- result.hits.hits.forEach(function (hit) {
- var fields = {};
- fields.package_name = hit.fields.package_name[0];
- fields.version = hit.fields.version[0];
- fields.maintainer = hit.fields["maintainer.name"];
- var highlights = _.mapValues(hit.highlight, function (highlight) {
- return striptags(highlight.toString(), "");
- });
-
- var description = highlights.description || hit.fields.description[0];
-
- packages.push({
- description: description,
- fields: fields,
- score: hit._score,
- });
+ from: offset,
+ size: perPage,
+ fields: ['package_name', 'version', 'description', 'maintainer.name']
+ }
+ }).then(function(result) {
+ var packages = [];
+ result.hits.hits.forEach(function(hit) {
+ var fields = {};
+ fields.package_name = hit.fields.package_name[0];
+ fields.version = hit.fields.version[0];
+ fields.maintainer = hit.fields['maintainer.name'];
+ var highlights = _.mapValues(hit.highlight, function(highlight) {
+ return striptags(highlight.toString(), '');
});
- res.locals.layout = null;
- if (req.headers.accept === "application/json") {
- return res.json({
- packages: packages,
- hits: result.hits.total,
- });
- }
- return res.view("search/package_results.ejs", {
- data: {
- packages: packages,
- hits: numeral(result.hits.total).format("0,0"),
- },
+
+ var description = highlights.description || hit.fields.description[0];
+
+ packages.push({
+ description: description,
+ fields: fields,
+ score: hit._score
});
- })
- .catch(function (err) {
- return res.negotiate(err);
});
+ res.locals.layout = null;
+ if (req.headers.accept === 'application/json') {
+ return res.json({
+ packages: packages, hits: result.hits.total
+ });
+ }
+ return res.view('search/package_results.ejs', { data: {packages: packages, hits: numeral(result.hits.total).format('0,0')}});
+ }).catch(function(err) {
+ return res.negotiate(err);
+ });
},
- functionSearch: function (req, res) {
- var query = req.param("q");
- var package = req.param("package");
- var page = parseInt(req.param("page")) || 1;
- var perPage = parseInt(req.param("perPage")) || 15;
- var onlyLatestVersion = parseInt(req.param("latest")) === 1;
+ functionSearch: function(req, res) {
+ var query = req.param('q');
+ var package = req.param('package');
+ var page = parseInt(req.param('page')) || 1;
+ var perPage = parseInt(req.param('perPage')) || 15;
+ var onlyLatestVersion = (parseInt(req.param('latest'))) === 1;
var offset = (page - 1) * perPage;
var searchTopicQuery = {
multi_match: {
query: query,
- type: "best_fields",
+ type: 'best_fields',
boost: 1,
fields: [
- "aliases^6",
- "name^2",
- "title^2",
- "description",
- "keywords^2",
- "arguments.name",
- "arguments.description",
- "details",
- "value",
- "note",
- "author",
- ],
- },
+ 'aliases^6',
+ 'name^2',
+ 'title^2', 'description', 'keywords^2',
+ 'arguments.name', 'arguments.description',
+ 'details', 'value',
+ 'note', 'author']
+ }
};
var prefixQuery = {
- multi_match: {
+ 'multi_match': {
boost: 0.2,
- fields: ["aliases^2", "name"],
- query: query,
- type: "phrase_prefix",
- },
+ 'fields': ['aliases^2', 'name'],
+ 'query': query,
+ 'type': 'phrase_prefix'
+ }
};
var topicFilter = [
{
type: {
- value: "topic",
- },
- },
+ value: 'topic'
+ }
+ }
];
var packageMatchQuery;
if (package === undefined) {
packageMatchQuery = {
has_parent: {
- parent_type: "package_version",
- },
+ parent_type: 'package_version'
+ }
};
if (onlyLatestVersion) {
- packageMatchQuery.has_parent.query = { term: { latest_version: 1 } };
+ packageMatchQuery.has_parent.query = { term: { latest_version: 1 } };
topicFilter.push(packageMatchQuery);
}
- } else {
+ } else {
packageMatchQuery = {
has_parent: {
- parent_type: "package_version",
+ parent_type: 'package_version',
query: {
- bool: {
- must: [
+ 'bool': {
+ 'must': [
{
- term: { package_name: package },
- },
- ],
- },
- },
- },
+ term: { package_name: package }
+ }
+ ]
+ }
+ }
+ }
};
- if (onlyLatestVersion) {
- packageMatchQuery.has_parent.query.bool.must.push({
- term: { latest_version: 1 },
- });
- }
+ if (onlyLatestVersion) {packageMatchQuery.has_parent.query.bool.must.push({term: { latest_version: 1 }});}
topicFilter.push(packageMatchQuery);
}
- return es
- .search({
- index: "rdoc",
- body: {
- query: {
- bool: {
- should: [
- {
- bool: {
- filter: topicFilter,
- should: [
- searchTopicQuery,
- prefixQuery,
- {
- has_parent: {
- parent_type: "package_version",
- score_mode: "score",
-
- query: {
- has_parent: {
- parent_type: "package",
- score_mode: "score",
- query: {
- function_score: {
- functions: [
- {
- filter: {
- missing: { field: "part_of_r" },
- },
- field_value_factor: {
- field: "last_month_downloads",
- modifier: "log1p",
- },
- },
- {
- filter: { term: { part_of_r: 0 } },
- field_value_factor: {
- field: "last_month_downloads",
- modifier: "log1p",
- },
- },
- {
- filter: { term: { part_of_r: 1 } },
- field_value_factor: {
- field: "part_of_r",
- modifier: "log1p",
- factor: 3000,
- },
- },
- ],
- boost_mode: "replace",
- },
- },
- },
- },
- inner_hits: {
- fields: [
- "package_name",
- "version",
- "latest_version",
- "maintainer.name",
- ],
- },
+ return es.search({
+ index: 'rdoc',
+ body: {
+ query: {
+ bool: {
+ should: [
+ {
+ bool: {
+ filter: topicFilter,
+ should: [
+ searchTopicQuery,
+ prefixQuery,
+ {
+ has_parent: {
+ parent_type: 'package_version',
+ score_mode: 'score',
+
+ query: {
+ 'has_parent': {
+ 'parent_type': 'package',
+ 'score_mode': 'score',
+ 'query': {
+ 'function_score': {
+ 'functions': [
+ {
+ 'filter': { 'missing': { 'field': 'part_of_r' } },
+ 'field_value_factor': {
+ 'field': 'last_month_downloads',
+ 'modifier': 'log1p'
+ }
+ },
+ {
+ 'filter': { 'term': { 'part_of_r': 0 } },
+ 'field_value_factor': {
+ 'field': 'last_month_downloads',
+ 'modifier': 'log1p'
+ }
+ },
+ {
+ 'filter': { 'term': { 'part_of_r': 1 } },
+ 'field_value_factor': {
+ 'field': 'part_of_r',
+ 'modifier': 'log1p',
+ 'factor': 3000
+ }
+ }
+ ],
+ 'boost_mode': 'replace'
+ }
+ }
+ }
},
- },
- ],
- minimum_should_match: 1,
- },
- },
- ],
- minimum_should_match: 1,
- },
- },
- highlight: {
- pre_tags: [""],
- post_tags: [""],
- fields: {
- description: {
- number_of_fragments: 0,
- highlight_query: searchTopicQuery,
- },
- title: {
- number_of_fragments: 0,
- highlight_query: searchTopicQuery,
- },
+ inner_hits: { fields: ['package_name', 'version', 'latest_version', 'maintainer.name'] }
+ }
+ }
+ ],
+ minimum_should_match: 1
+ }
+ }],
+ minimum_should_match: 1
+ }
+ },
+ highlight: {
+ pre_tags: [''],
+ post_tags: [''],
+ 'fields': {
+ 'description': {
+ 'number_of_fragments': 0,
+ highlight_query: searchTopicQuery
},
- },
- from: offset,
- size: perPage,
- fields: [
- "package_name",
- "version",
- "name",
- "maintainer.name",
- "description",
- "title",
- ],
+ 'title': {
+ 'number_of_fragments': 0,
+ highlight_query: searchTopicQuery}
+ }
},
- })
- .then(function (result) {
- var functions = [];
- result.hits.hits.forEach(function (hit) {
- var fields = {};
- var inner_hits_fields =
- hit.inner_hits.package_version.hits.hits[0].fields;
- fields.package_name = inner_hits_fields.package_name[0];
- fields.version = inner_hits_fields.version[0];
- fields.name = hit.fields.name[0];
- fields.maintainer =
- inner_hits_fields && inner_hits_fields["maintainer.name"]
- ? inner_hits_fields["maintainer.name"][0]
- : undefined;
-
- var highlights = _.mapValues(hit.highlight, function (highlight) {
- return striptags(highlight.toString(), "");
- });
-
- var description = highlights.description || hit.fields.description[0];
- var title = highlights.title || hit.fields.title[0];
-
- functions.push({
- fields: fields,
- score: hit._score,
- description: description,
- title: title,
- });
+ from: offset,
+ size: perPage,
+ fields: ['package_name', 'version', 'name', 'maintainer.name', 'description', 'title']
+ }
+ }).then(function(result) {
+ var functions = [];
+ result.hits.hits.forEach(function(hit) {
+ var fields = {};
+ var inner_hits_fields = hit.inner_hits.package_version.hits.hits[0].fields;
+ fields.package_name = inner_hits_fields.package_name[0];
+ fields.version = inner_hits_fields.version[0];
+ fields.name = hit.fields.name[0];
+ fields.maintainer = (inner_hits_fields && inner_hits_fields['maintainer.name'])
+ ? inner_hits_fields['maintainer.name'][0]
+ : undefined;
+
+ var highlights = _.mapValues(hit.highlight, function(highlight) {
+ return striptags(highlight.toString(), '');
});
- res.locals.layout = null;
- if (req.headers.accept === "application/json") {
- return res.json({
- functions: functions,
- hits: result.hits.total,
- });
- }
- return res.view("search/function_results.ejs", {
- data: {
- functions: functions,
- hits: numeral(result.hits.total).format("0,0"),
- },
+
+ var description = highlights.description || hit.fields.description[0];
+ var title = highlights.title || hit.fields.title[0];
+
+ functions.push({
+ fields: fields,
+ score: hit._score,
+ description: description,
+ title: title
});
- })
- .catch(function (err) {
- return res.negotiate(err);
});
+ res.locals.layout = null;
+ if (req.headers.accept === 'application/json') {
+ return res.json({
+ functions: functions, hits: result.hits.total
+ });
+ }
+ return res.view('search/function_results.ejs', {data: {functions: functions, hits: numeral(result.hits.total).format('0,0')}});
+ }).catch(function(err) {
+ return res.negotiate(err);
+ });
},
- fullSearch: function (req, res) {
- return res.redirect(
- 302,
- "https://rdocumentation.org/search?q=" + req.param("q")
- );
- },
+
+ fullSearch: function(req, res) {
+ return res.redirect(302, "https://rdocumentation.org/search?q=" + req.param('q'));
+ }
+
};