diff --git a/services/madoc-ts/src/capture-model-server/capture-model-repository.ts b/services/madoc-ts/src/capture-model-server/capture-model-repository.ts index df32540ff..3e5d2e0b4 100644 --- a/services/madoc-ts/src/capture-model-server/capture-model-repository.ts +++ b/services/madoc-ts/src/capture-model-server/capture-model-repository.ts @@ -136,6 +136,7 @@ export class CaptureModelRepository extends BaseRepository<'capture_model_api_mi derivedFrom, all, target, + searchQuery, }: { page?: number; perPage?: number; @@ -143,6 +144,7 @@ export class CaptureModelRepository extends BaseRepository<'capture_model_api_mi derivedFrom?: string; all?: boolean; target?: string; + searchQuery?: string; }, site_id: number ) { @@ -161,6 +163,14 @@ export class CaptureModelRepository extends BaseRepository<'capture_model_api_mi })}::jsonb) is not null` : sql``; + const search = searchQuery + ? `and cm.id in (${CaptureModelRepository.queries.documentSearch( + searchQuery, + { allDerivatives, derivedFrom, target }, + site_id + )})` + : sql``; + return sql` select cm.id, cm.derived_from, @@ -173,6 +183,7 @@ export class CaptureModelRepository extends BaseRepository<'capture_model_api_mi where cm.site_id = ${site_id} ${derivedQuery} ${targetQuery} + ${search} ${paging} `; }, @@ -201,6 +212,34 @@ export class CaptureModelRepository extends BaseRepository<'capture_model_api_mi ${paging} `; }, + + documentSearch(query: string, { derivedFrom, allDerivatives, target }: any, site_id: number) { + const derivedQuery = derivedFrom + ? sql`and cmn.derived_from = ${derivedFrom}` + : allDerivatives + ? sql`` + : sql`and cmn.derived_from is null`; + + const targetQuery = target + ? sql` + and jsonb_path_query_first(cmn.target::jsonb, '$[*] ? (@.id == $target)', ${sql.json({ + target, + })}::jsonb) is not null` + : sql``; + + return sql<{ id: string }>` + select r.id + from capture_model_document r left join capture_model cmn on r.id = cmn.document_id, + jsonb_to_recordset(jsonb_path_query_array(document_data -> 'properties', + '$.*[0] ? (@.type == "entity")."properties".*[0]')) as entity(id text, value text, type text), + jsonb_to_recordset(jsonb_path_query_array(document_data -> 'properties', + '$.*[0] ? (@.value != null)')) as field(id text, value text) + where (field.value::text ilike ${`%${query}%`} or entity.value::text ilike ${`%${query}%`}) + and cmn.site_id = ${site_id} + ${derivedQuery} + ${targetQuery} + `; + }, }; static mutations = { createDocument: (doc: CaptureModel['document'], site_id: number, target?: CaptureModel['target']) => { @@ -611,6 +650,7 @@ export class CaptureModelRepository extends BaseRepository<'capture_model_api_mi derivedFrom?: string; all?: boolean; target?: string; + searchQuery?: string; }, siteId: number ): Promise { @@ -1108,7 +1148,42 @@ export class CaptureModelRepository extends BaseRepository<'capture_model_api_mi }); } - async searchPublished(siteId: number) { + async searchPublished( + siteId: number, + query: string, + options: { + manifest?: string; + canvas?: string; + collection?: string; + field_type?: string; + parent_property?: string; + selector_type?: string; + capture_model_id?: string; + } = {} + ) { + // Is this the correct return type? + // return this.listCaptureModels( + // { + // page: 0, + // perPage: 100, + // all: true, + // target: options.manifest || options.canvas, + // derivedFrom: options.capture_model_id, + // searchQuery: query, + // }, + // siteId + // ); + + // options.manifest / options.canvas / options.collection + // | JSON query on the target field, can be grabbed from existing codebase + // + // options.field_type / options.parent_property / options.selector_type + // | No easy way to achieve this at the moment. It could be shallow - and use a query, otherwise it would + // | Have to be a post-filter. + // + // options.capture_model_id + // | Simple enough field check. + // @todo this does need to be re-implemented for the search manifest functionality to work // however this might be a good time to use the actual search service for that instead. return []; diff --git a/services/madoc-ts/src/capture-model-server/routes/search-published.ts b/services/madoc-ts/src/capture-model-server/routes/search-published.ts index 5c90b2d62..b6834972e 100644 --- a/services/madoc-ts/src/capture-model-server/routes/search-published.ts +++ b/services/madoc-ts/src/capture-model-server/routes/search-published.ts @@ -4,34 +4,42 @@ import { optionalUserWithScope } from '../../utility/user-with-scope'; export const searchPublished: RouteMiddleware = async context => { const { siteId } = optionalUserWithScope(context, ['models.view_published']); - // const { q: query, manifest, canvas, collection, field_type, parent_property, selector_type, capture_model_id } = - // (ctx.request.query as any) || {}; - // - // const queryBlock: any = {}; - // - // if (manifest) { - // queryBlock.manifest = manifest; - // } - // if (canvas) { - // queryBlock.canvas = canvas; - // } - // if (collection) { - // queryBlock.collection = collection; - // } - // if (field_type) { - // queryBlock.field_type = field_type; - // } - // if (parent_property) { - // queryBlock.parent_property = parent_property; - // } - // if (selector_type) { - // queryBlock.selector_type = selector_type; - // } - // if (capture_model_id) { - // queryBlock.capture_model_id = capture_model_id; - // } + const { q: query, manifest, canvas, collection, field_type, parent_property, selector_type, capture_model_id } = + (context.query as any) || {}; + + const queryBlock: { + manifest?: string; + canvas?: string; + collection?: string; + field_type?: string; + parent_property?: string; + selector_type?: string; + capture_model_id?: string; + } = {}; + + if (manifest) { + queryBlock.manifest = manifest; + } + if (canvas) { + queryBlock.canvas = canvas; + } + if (collection) { + queryBlock.collection = collection; + } + if (field_type) { + queryBlock.field_type = field_type; + } + if (parent_property) { + queryBlock.parent_property = parent_property; + } + if (selector_type) { + queryBlock.selector_type = selector_type; + } + if (capture_model_id) { + queryBlock.capture_model_id = capture_model_id; + } context.response.body = { - results: await context.captureModels.searchPublished(siteId), + results: await context.captureModels.searchPublished(siteId, query, queryBlock), }; };