Add jsdoc to search utils
This commit is contained in:
parent
8e2aff1716
commit
f54096447d
|
@ -3,10 +3,20 @@ const { checkSlashesInUrl } = require("../../../utilities")
|
|||
const env = require("../../../environment")
|
||||
const fetch = require("node-fetch")
|
||||
|
||||
/**
|
||||
* Escapes any characters in a string which lucene searches require to be
|
||||
* escaped.
|
||||
* @param value The value to escape
|
||||
* @returns {string}
|
||||
*/
|
||||
const luceneEscape = value => {
|
||||
return `${value}`.replace(/[ #+\-&|!(){}\[\]^"~*?:\\]/g, "\\$&")
|
||||
}
|
||||
|
||||
/**
|
||||
* Class to build lucene query URLs.
|
||||
* Optionally takes a base lucene query object.
|
||||
*/
|
||||
class QueryBuilder {
|
||||
constructor(appId, base) {
|
||||
this.appId = appId
|
||||
|
@ -105,6 +115,7 @@ class QueryBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
// Construct the actual lucene search query string from JSON structure
|
||||
if (this.query.string) {
|
||||
build(this.query.string, (key, value) => {
|
||||
return value ? `${key}:${luceneEscape(value.toLowerCase())}*` : null
|
||||
|
@ -146,6 +157,7 @@ class QueryBuilder {
|
|||
build(this.query.notEmpty, key => `${key}:["" TO *]`)
|
||||
}
|
||||
|
||||
// Build the full search URL
|
||||
let url = `${env.COUCH_DB_URL}/${this.appId}/_design/database/_search`
|
||||
url += `/${SearchIndexes.ROWS}?q=${output}`
|
||||
url += `&limit=${Math.min(this.limit, 200)}`
|
||||
|
@ -161,11 +173,18 @@ class QueryBuilder {
|
|||
if (this.bookmark) {
|
||||
url += `&bookmark=${this.bookmark}`
|
||||
}
|
||||
|
||||
console.log(url)
|
||||
// Fix any double slashes in the URL
|
||||
return checkSlashesInUrl(url)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a lucene search query.
|
||||
* @param query The query URL
|
||||
* @returns {Promise<{rows: []}>}
|
||||
*/
|
||||
const runQuery = async query => {
|
||||
const response = await fetch(query, {
|
||||
method: "GET",
|
||||
|
@ -183,6 +202,22 @@ const runQuery = async query => {
|
|||
return output
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets round the fixed limit of 200 results from a query by fetching as many
|
||||
* pages as required and concatenating the results. This recursively operates
|
||||
* until enough results have been found.
|
||||
* @param appId {string} The app ID to search
|
||||
* @param query {object} The JSON query structure
|
||||
* @param tableId {string} The table ID to search
|
||||
* @param sort {string} The sort column
|
||||
* @param sortOrder {string} The sort order ("ascending" or "descending")
|
||||
* @param sortType {string} Whether to treat sortable values as strings or
|
||||
* numbers. ("string" or "number")
|
||||
* @param limit {number} The number of results to fetch
|
||||
* @param bookmark {string|null} Current bookmark in the recursive search
|
||||
* @param rows {array|null} Current results in the recursive search
|
||||
* @returns {Promise<*[]|*>}
|
||||
*/
|
||||
const recursiveSearch = async (
|
||||
appId,
|
||||
query,
|
||||
|
@ -191,8 +226,8 @@ const recursiveSearch = async (
|
|||
sortOrder,
|
||||
sortType,
|
||||
limit,
|
||||
bookmark,
|
||||
rows
|
||||
bookmark = null,
|
||||
rows = []
|
||||
) => {
|
||||
if (rows.length >= limit) {
|
||||
return rows
|
||||
|
@ -226,6 +261,21 @@ const recursiveSearch = async (
|
|||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a paginated search. A bookmark will be returned to allow the next
|
||||
* page to be fetched. There is a max limit off 200 results per page in a
|
||||
* paginated search.
|
||||
* @param appId {string} The app ID to search
|
||||
* @param query {object} The JSON query structure
|
||||
* @param tableId {string} The table ID to search
|
||||
* @param sort {string} The sort column
|
||||
* @param sortOrder {string} The sort order ("ascending" or "descending")
|
||||
* @param sortType {string} Whether to treat sortable values as strings or
|
||||
* numbers. ("string" or "number")
|
||||
* @param limit {number} The desired page size
|
||||
* @param bookmark {string} The bookmark to resume from
|
||||
* @returns {Promise<{hasNextPage: boolean, rows: *[]}>}
|
||||
*/
|
||||
exports.paginatedSearch = async (
|
||||
appId,
|
||||
query,
|
||||
|
@ -239,6 +289,7 @@ exports.paginatedSearch = async (
|
|||
if (limit == null || isNaN(limit) || limit < 0) {
|
||||
limit = 50
|
||||
}
|
||||
limit = Math.min(limit, 200)
|
||||
const builder = new QueryBuilder(appId, query)
|
||||
.setTable(tableId)
|
||||
.setSort(sort)
|
||||
|
@ -249,17 +300,36 @@ exports.paginatedSearch = async (
|
|||
.setLimit(limit)
|
||||
.buildSearchURL()
|
||||
const searchResults = await runQuery(searchUrl)
|
||||
|
||||
// Try fetching 1 row in the next page to see if another page of results
|
||||
// exists or not
|
||||
const nextUrl = builder
|
||||
.setBookmark(searchResults.bookmark)
|
||||
.setLimit(1)
|
||||
.buildSearchURL()
|
||||
const nextResults = await runQuery(nextUrl)
|
||||
|
||||
return {
|
||||
...searchResults,
|
||||
hasNextPage: nextResults.rows && nextResults.rows.length > 0,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a full search, fetching multiple pages if required to return the
|
||||
* desired amount of results. There is a limit of 1000 results to avoid
|
||||
* heavy performance hits, and to avoid client components breaking from
|
||||
* handling too much data.
|
||||
* @param appId {string} The app ID to search
|
||||
* @param query {object} The JSON query structure
|
||||
* @param tableId {string} The table ID to search
|
||||
* @param sort {string} The sort column
|
||||
* @param sortOrder {string} The sort order ("ascending" or "descending")
|
||||
* @param sortType {string} Whether to treat sortable values as strings or
|
||||
* numbers. ("string" or "number")
|
||||
* @param limit {number} The desired number of results
|
||||
* @returns {Promise<{rows: *}>}
|
||||
*/
|
||||
exports.fullSearch = async (
|
||||
appId,
|
||||
query,
|
||||
|
@ -272,6 +342,7 @@ exports.fullSearch = async (
|
|||
if (limit == null || isNaN(limit) || limit < 0) {
|
||||
limit = 1000
|
||||
}
|
||||
limit = Math.min(limit, 1000)
|
||||
const rows = await recursiveSearch(
|
||||
appId,
|
||||
query,
|
||||
|
@ -279,9 +350,7 @@ exports.fullSearch = async (
|
|||
sort,
|
||||
sortOrder,
|
||||
sortType,
|
||||
Math.min(limit, 1000),
|
||||
null,
|
||||
[]
|
||||
limit
|
||||
)
|
||||
return { rows }
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue