Finishing up search API, updating typing in lucene layer.
This commit is contained in:
parent
6ec5e97ce9
commit
eca34d73ed
2 changed files with 67 additions and 35 deletions
|
@ -4,14 +4,25 @@ import { SearchFilters, Row } from "@budibase/types"
|
||||||
|
|
||||||
const QUERY_START_REGEX = /\d[0-9]*:/g
|
const QUERY_START_REGEX = /\d[0-9]*:/g
|
||||||
|
|
||||||
|
interface SearchResponse<T> {
|
||||||
|
rows: T[] | any[]
|
||||||
|
bookmark: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PaginatedSearchResponse<T> extends SearchResponse<T> {
|
||||||
|
hasNextPage: boolean
|
||||||
|
}
|
||||||
|
|
||||||
export type SearchParams = {
|
export type SearchParams = {
|
||||||
tableId: string
|
tableId?: string
|
||||||
sort?: string
|
sort?: string
|
||||||
sortOrder?: string
|
sortOrder?: string
|
||||||
sortType?: string
|
sortType?: string
|
||||||
limit?: number
|
limit?: number
|
||||||
bookmark?: string
|
bookmark?: string
|
||||||
version?: string
|
version?: string
|
||||||
|
indexer?: () => Promise<any>
|
||||||
|
disableEscaping?: boolean
|
||||||
rows?: Row[]
|
rows?: Row[]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +41,7 @@ export function removeKeyNumbering(key: any): string {
|
||||||
* Class to build lucene query URLs.
|
* Class to build lucene query URLs.
|
||||||
* Optionally takes a base lucene query object.
|
* Optionally takes a base lucene query object.
|
||||||
*/
|
*/
|
||||||
export class QueryBuilder {
|
export class QueryBuilder<T> {
|
||||||
dbName: string
|
dbName: string
|
||||||
index: string
|
index: string
|
||||||
query: SearchFilters
|
query: SearchFilters
|
||||||
|
@ -70,10 +81,12 @@ export class QueryBuilder {
|
||||||
|
|
||||||
disableEscaping() {
|
disableEscaping() {
|
||||||
this.noEscaping = true
|
this.noEscaping = true
|
||||||
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
setIndexBuilder(builderFn: () => Promise<any>) {
|
setIndexBuilder(builderFn: () => Promise<any>) {
|
||||||
this.indexBuilder = builderFn
|
this.indexBuilder = builderFn
|
||||||
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
setVersion(version?: string) {
|
setVersion(version?: string) {
|
||||||
|
@ -407,11 +420,11 @@ export class QueryBuilder {
|
||||||
const fullPath = `${url}/${this.dbName}/_design/database/_search/${this.index}`
|
const fullPath = `${url}/${this.dbName}/_design/database/_search/${this.index}`
|
||||||
const body = this.buildSearchBody()
|
const body = this.buildSearchBody()
|
||||||
try {
|
try {
|
||||||
return await runQuery(fullPath, body, cookie)
|
return await runQuery<T>(fullPath, body, cookie)
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err.status === 404 && this.indexBuilder) {
|
if (err.status === 404 && this.indexBuilder) {
|
||||||
await this.indexBuilder()
|
await this.indexBuilder()
|
||||||
return await runQuery(fullPath, body, cookie)
|
return await runQuery<T>(fullPath, body, cookie)
|
||||||
} else {
|
} else {
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
|
@ -426,7 +439,11 @@ export class QueryBuilder {
|
||||||
* @param cookie The auth cookie for CouchDB
|
* @param cookie The auth cookie for CouchDB
|
||||||
* @returns {Promise<{rows: []}>}
|
* @returns {Promise<{rows: []}>}
|
||||||
*/
|
*/
|
||||||
const runQuery = async (url: string, body: any, cookie: string) => {
|
async function runQuery<T>(
|
||||||
|
url: string,
|
||||||
|
body: any,
|
||||||
|
cookie: string
|
||||||
|
): Promise<SearchResponse<T>> {
|
||||||
const response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
method: "POST",
|
method: "POST",
|
||||||
|
@ -470,7 +487,7 @@ const runQuery = async (url: string, body: any, cookie: string) => {
|
||||||
* rows {array|null} Current results in the recursive search
|
* rows {array|null} Current results in the recursive search
|
||||||
* @returns {Promise<*[]|*>}
|
* @returns {Promise<*[]|*>}
|
||||||
*/
|
*/
|
||||||
async function recursiveSearch(
|
async function recursiveSearch<T>(
|
||||||
dbName: string,
|
dbName: string,
|
||||||
index: string,
|
index: string,
|
||||||
query: any,
|
query: any,
|
||||||
|
@ -485,7 +502,7 @@ async function recursiveSearch(
|
||||||
if (rows.length > params.limit - 200) {
|
if (rows.length > params.limit - 200) {
|
||||||
pageSize = params.limit - rows.length
|
pageSize = params.limit - rows.length
|
||||||
}
|
}
|
||||||
const page = await new QueryBuilder(dbName, index, query)
|
const page = await new QueryBuilder<T | Row>(dbName, index, query)
|
||||||
.setVersion(params.version)
|
.setVersion(params.version)
|
||||||
.setTable(params.tableId)
|
.setTable(params.tableId)
|
||||||
.setBookmark(bookmark)
|
.setBookmark(bookmark)
|
||||||
|
@ -525,7 +542,7 @@ async function recursiveSearch(
|
||||||
* bookmark {string} The bookmark to resume from
|
* bookmark {string} The bookmark to resume from
|
||||||
* @returns {Promise<{hasNextPage: boolean, rows: *[]}>}
|
* @returns {Promise<{hasNextPage: boolean, rows: *[]}>}
|
||||||
*/
|
*/
|
||||||
export async function paginatedSearch(
|
export async function paginatedSearch<T>(
|
||||||
dbName: string,
|
dbName: string,
|
||||||
index: string,
|
index: string,
|
||||||
query: SearchFilters,
|
query: SearchFilters,
|
||||||
|
@ -536,12 +553,25 @@ export async function paginatedSearch(
|
||||||
limit = 50
|
limit = 50
|
||||||
}
|
}
|
||||||
limit = Math.min(limit, 200)
|
limit = Math.min(limit, 200)
|
||||||
const search = new QueryBuilder(dbName, index, query)
|
const search = new QueryBuilder<T | Row>(dbName, index, query)
|
||||||
.setVersion(params.version)
|
if (params.version) {
|
||||||
.setTable(params.tableId)
|
search.setVersion(params.version)
|
||||||
.setSort(params.sort)
|
}
|
||||||
.setSortOrder(params.sortOrder)
|
if (params.tableId) {
|
||||||
.setSortType(params.sortType)
|
search.setTable(params.tableId)
|
||||||
|
}
|
||||||
|
if (params.sort) {
|
||||||
|
search
|
||||||
|
.setSort(params.sort)
|
||||||
|
.setSortOrder(params.sortOrder)
|
||||||
|
.setSortType(params.sortType)
|
||||||
|
}
|
||||||
|
if (params.indexer) {
|
||||||
|
search.setIndexBuilder(params.indexer)
|
||||||
|
}
|
||||||
|
if (params.disableEscaping) {
|
||||||
|
search.disableEscaping()
|
||||||
|
}
|
||||||
const searchResults = await search
|
const searchResults = await search
|
||||||
.setBookmark(params.bookmark)
|
.setBookmark(params.bookmark)
|
||||||
.setLimit(limit)
|
.setLimit(limit)
|
||||||
|
@ -549,11 +579,11 @@ export async function paginatedSearch(
|
||||||
|
|
||||||
// Try fetching 1 row in the next page to see if another page of results
|
// Try fetching 1 row in the next page to see if another page of results
|
||||||
// exists or not
|
// exists or not
|
||||||
const nextResults = await search
|
search.setBookmark(searchResults.bookmark).setLimit(1)
|
||||||
.setTable(params.tableId)
|
if (params.tableId) {
|
||||||
.setBookmark(searchResults.bookmark)
|
search.setTable(params.tableId)
|
||||||
.setLimit(1)
|
}
|
||||||
.run()
|
const nextResults = await search.run()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...searchResults,
|
...searchResults,
|
||||||
|
@ -578,7 +608,7 @@ export async function paginatedSearch(
|
||||||
* limit {number} The desired number of results
|
* limit {number} The desired number of results
|
||||||
* @returns {Promise<{rows: *}>}
|
* @returns {Promise<{rows: *}>}
|
||||||
*/
|
*/
|
||||||
export async function fullSearch(
|
export async function fullSearch<T>(
|
||||||
dbName: string,
|
dbName: string,
|
||||||
index: string,
|
index: string,
|
||||||
query: SearchFilters,
|
query: SearchFilters,
|
||||||
|
@ -589,6 +619,6 @@ export async function fullSearch(
|
||||||
limit = 1000
|
limit = 1000
|
||||||
}
|
}
|
||||||
params.limit = Math.min(limit, 1000)
|
params.limit = Math.min(limit, 1000)
|
||||||
const rows = await recursiveSearch(dbName, index, query, params)
|
const rows = await recursiveSearch<T | Row>(dbName, index, query, params)
|
||||||
return { rows }
|
return { rows }
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,21 +16,23 @@ export interface SearchAuditLogsRequest
|
||||||
extends PaginationRequest,
|
extends PaginationRequest,
|
||||||
AuditLogSearchParams {}
|
AuditLogSearchParams {}
|
||||||
|
|
||||||
export interface SearchAuditLogsResponse extends PaginationResponse {
|
export interface AuditLogEnriched {
|
||||||
data: {
|
app: {
|
||||||
app: {
|
_id: string
|
||||||
_id: string
|
|
||||||
name: string
|
|
||||||
}
|
|
||||||
user: {
|
|
||||||
_id: string
|
|
||||||
name: string
|
|
||||||
}
|
|
||||||
event: Event
|
|
||||||
timestamp: string
|
|
||||||
name: string
|
name: string
|
||||||
metadata: any
|
}
|
||||||
}[]
|
user: {
|
||||||
|
_id: string
|
||||||
|
name: string
|
||||||
|
}
|
||||||
|
event: Event
|
||||||
|
timestamp: string
|
||||||
|
name: string
|
||||||
|
metadata: any
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchAuditLogsResponse extends PaginationResponse {
|
||||||
|
data: AuditLogEnriched[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DefinitionsAuditLogsResponse {
|
export interface DefinitionsAuditLogsResponse {
|
||||||
|
|
Loading…
Reference in a new issue