diff --git a/examples/nuxt-app/test/features/search-listing/result-items.feature b/examples/nuxt-app/test/features/search-listing/result-items.feature index 69f91e0454..c60d1290ff 100644 --- a/examples/nuxt-app/test/features/search-listing/result-items.feature +++ b/examples/nuxt-app/test/features/search-listing/result-items.feature @@ -17,3 +17,31 @@ Feature: Result items | Accessibility guidelines | tide-search-result-card | | Small business grant | tide-grant-search-result | | GovHack 2022 is coming | tide-search-result | + + @mockserver + Example: Result contents from elasticsearch can be customised to exclude fields + Given I load the page fixture with "/search-listing/result-items/page" + And the search listing config has the following excludes added to source + | key | + | nid | + | field_node_site | + Then the page endpoint for path "/search-results" returns the loaded fixture + And the search network request is stubbed with fixture "/search-listing/result-items/response" and status 200 + + When I visit the page "/search-results" + Then the search listing page should have 4 results + And the search network request should be called with the "/search-listing/result-items/request-source-exclude" fixture + + @mockserver + Example: Result contents from elasticsearch can be customised to include fields + Given I load the page fixture with "/search-listing/result-items/page" + And the search listing config has the following includes added to source + | key | + | title | + | field_summary | + Then the page endpoint for path "/search-results" returns the loaded fixture + And the search network request is stubbed with fixture "/search-listing/result-items/response" and status 200 + + When I visit the page "/search-results" + Then the search listing page should have 4 results + And the search network request should be called with the "/search-listing/result-items/request-source-include" fixture diff --git a/examples/nuxt-app/test/fixtures/search-listing/result-items/request-source-exclude.json b/examples/nuxt-app/test/fixtures/search-listing/result-items/request-source-exclude.json new file mode 100644 index 0000000000..2dde0c2607 --- /dev/null +++ b/examples/nuxt-app/test/fixtures/search-listing/result-items/request-source-exclude.json @@ -0,0 +1,40 @@ +{ + "query": { + "bool": { + "must": [ + { + "match_all": {} + } + ], + "filter": [ + { + "terms": { + "type": [ + "news", + "grant", + "event", + "landing_page" + ] + } + }, + { + "terms": { + "field_node_site": [ + 8888 + ] + } + } + ] + } + }, + "size": 20, + "from": 0, + "sort": [ + { + "title.keyword": "asc" + } + ], + "_source": { + "exclude": ["nid", "field_node_site"] + } +} diff --git a/examples/nuxt-app/test/fixtures/search-listing/result-items/request-source-include.json b/examples/nuxt-app/test/fixtures/search-listing/result-items/request-source-include.json new file mode 100644 index 0000000000..fb0a3f512a --- /dev/null +++ b/examples/nuxt-app/test/fixtures/search-listing/result-items/request-source-include.json @@ -0,0 +1,43 @@ +{ + "query": { + "bool": { + "must": [ + { + "match_all": {} + } + ], + "filter": [ + { + "terms": { + "type": [ + "news", + "grant", + "event", + "landing_page" + ] + } + }, + { + "terms": { + "field_node_site": [ + 8888 + ] + } + } + ] + } + }, + "size": 20, + "from": 0, + "sort": [ + { + "title.keyword": "asc" + } + ], + "_source": { + "include": [ + "title", + "field_summary" + ] + } +} diff --git a/packages/ripple-test-utils/step_definitions/content-types/listing.ts b/packages/ripple-test-utils/step_definitions/content-types/listing.ts index 3457e2112c..627b246506 100644 --- a/packages/ripple-test-utils/step_definitions/content-types/listing.ts +++ b/packages/ripple-test-utils/step_definitions/content-types/listing.ts @@ -592,3 +592,35 @@ Then( }) } ) + +Then( + 'the search listing config has the following excludes added to source', + (dataTable: DataTable) => { + const table = dataTable.hashes() + const excludes = table.map((row) => row.key) + + cy.get('@pageFixture').then((response) => { + set( + response, + `config.searchListingConfig.responseSource.exclude`, + excludes + ) + }) + } +) + +Then( + 'the search listing config has the following includes added to source', + (dataTable: DataTable) => { + const table = dataTable.hashes() + const includes = table.map((row) => row.key) + + cy.get('@pageFixture').then((response) => { + set( + response, + `config.searchListingConfig.responseSource.include`, + includes + ) + }) + } +) diff --git a/packages/ripple-tide-search/composables/useTideSearch.ts b/packages/ripple-tide-search/composables/useTideSearch.ts index 2b9c70583e..39564c14ab 100644 --- a/packages/ripple-tide-search/composables/useTideSearch.ts +++ b/packages/ripple-tide-search/composables/useTideSearch.ts @@ -274,6 +274,19 @@ export default ({ ] } + const getSourceOptions = () => { + let source: { include?: string[]; exclude?: string[] } = {} + + if (searchListingConfig?.responseSource?.include) { + source.include = searchListingConfig?.responseSource?.include + } + if (searchListingConfig?.responseSource?.exclude) { + source.exclude = searchListingConfig?.responseSource?.exclude + } + + return Object.keys(source).length ? source : false + } + const getUserFilters = (forAggregations = false) => { const filterValues: Record = { ...filterForm.value, @@ -510,13 +523,20 @@ export default ({ const getQueryDSL = async () => { const locationFilters = await getLocationFilterClause('listing') const query = getQueryClause([...getUserFilterClause(), ...locationFilters]) + const source = getSourceOptions() - return { + let queryDSL = { query, size: pageSize.value, from: pagingStart.value, sort: getSortClause() } + + if (source) { + queryDSL._source = source + } + + return queryDSL } const getQueryDSLForDynamicAggregations = async () => { @@ -553,14 +573,21 @@ export default ({ const getQueryDSLForMaps = async () => { const locationFilters = await getLocationFilterClause('map') const query = getQueryClause([...getUserFilterClause(), ...locationFilters]) + const source = getSourceOptions() - return { + let queryDSL = { query, // ES queries have a 10k result limit, maps struggle drawing more than this anyway. If you need more you will need to implement a loading strategy see : https://openlayers.org/en/latest/apidoc/module-ol_loadingstrategy.html size: 10000, from: 0, sort: getSortClause() } + + if (source) { + queryDSL._source = source + } + + return queryDSL } const getSearchResults = async (isFirstRun: boolean) => { diff --git a/packages/ripple-tide-search/types.ts b/packages/ripple-tide-search/types.ts index 04025174f6..16b069d7f8 100644 --- a/packages/ripple-tide-search/types.ts +++ b/packages/ripple-tide-search/types.ts @@ -296,6 +296,13 @@ export type TideSearchListingConfig = { * @description show filters in the sidebar? */ filtersInSidebar?: boolean + /** + * @description modify the elasticsearch response source + */ + responseSource?: { + include?: string[] + exclude?: string[] + } } /** * @description Tabs to display, key needs to be one of TideSearchListingTabKey