diff --git a/dbrepo-search-service/app/api/routes.py b/dbrepo-search-service/app/api/routes.py index b212c81d14a01b7656f709d0e27e959fc33cbd5b..be2812da9d0cb71fef278433c88635005611418b 100644 --- a/dbrepo-search-service/app/api/routes.py +++ b/dbrepo-search-service/app/api/routes.py @@ -152,11 +152,10 @@ def search(): req_body = request.json logging.debug('search request body: %s', req_body) search_term = req_body.get("search_term") - type = req_body.get("type") t1 = req_body.get("t1") t2 = req_body.get("t2") field = req_body.get("field") value = req_body.get("value") fieldValuePairs = req_body.get("field_value_pairs") - response = general_search(type, search_term, t1, t2, fieldValuePairs) + response = general_search(search_term, t1, t2, fieldValuePairs) return response, 200 diff --git a/dbrepo-search-service/app/opensearch_client.py b/dbrepo-search-service/app/opensearch_client.py index c3d3f575b7a4942c4dda21b9b66383e03b66082f..3ede632afeb23743e5793ff4000aedd55cce20d8 100644 --- a/dbrepo-search-service/app/opensearch_client.py +++ b/dbrepo-search-service/app/opensearch_client.py @@ -111,7 +111,7 @@ def get_fields_for_index(index): return fields_list -def general_search(type=None, search_term=None, t1=None, t2=None, fieldValuePairs=None): +def general_search(search_term=None, t1=None, t2=None, fieldValuePairs=None): """ Main method for seaching stuff in the opensearch db @@ -149,9 +149,6 @@ def general_search(type=None, search_term=None, t1=None, t2=None, fieldValuePair "is_public", ] queries = [] - if type is not None: - logging.debug("search for specific index: %s", type) - index = type if search_term is not None: logging.debug('query has search_term present') text_query = { @@ -177,6 +174,10 @@ def general_search(type=None, search_term=None, t1=None, t2=None, fieldValuePair logging.debug('query has fieldValuePairs present') musts = [] for field, value in fieldValuePairs.items(): + if field == "type" and value in searchable_indices: + logging.debug("search for specific index: %s", value) + index = value + continue if field in field_list: if field.startswith(index) and "." in field: new_field = field[field.index(".") + 1:len(field)] diff --git a/dbrepo-ui/api/search.service.js b/dbrepo-ui/api/search.service.js index e9dd6ddb7ea52583d18b0960ceccfe3a6c6fe405..85f2315c6945442a5cd35452227feb7873d2d264 100644 --- a/dbrepo-ui/api/search.service.js +++ b/dbrepo-ui/api/search.service.js @@ -6,8 +6,9 @@ class SearchService { return new Promise((resolve, reject) => { axios.get(`/api/search/${type}/fields`, { headers: { Accept: 'application/json' } }) .then((response) => { - const jsonResponse = response.data - resolve(jsonResponse) + const json = response.data + console.debug('fields result', json) + resolve(json) }) .catch((error) => { const { code, message } = error @@ -18,13 +19,15 @@ class SearchService { }) } - search (type, searchTerm, keyValuePairs) { + search (searchData) { + // transform values to what the search API expects + const searchTerm = searchData.search_term + delete searchData.search_term + searchData = Object.fromEntries(Object.entries(searchData).filter(([_, v]) => v != null)) // https://stackoverflow.com/questions/286141/remove-blank-attributes-from-an-object-in-javascript const payload = { - type, search_term: searchTerm, - field_value_pairs: { ...keyValuePairs } + field_value_pairs: { ...searchData } } - return new Promise((resolve, reject) => { axios.post('/api/search', payload, { headers: { Accept: 'application/json' } }) .then((response) => { diff --git a/dbrepo-ui/layouts/default.vue b/dbrepo-ui/layouts/default.vue index 77073f8de84d11a251828d3c593e36c7cd290c57..1d343810e1fcce8f50ffb41c69a8cda1076f137a 100644 --- a/dbrepo-ui/layouts/default.vue +++ b/dbrepo-ui/layouts/default.vue @@ -147,8 +147,7 @@ <v-row> <v-col cols="auto"> <v-select - v-model="advancedSearchType" - clearable + v-model="advancedSearchData.type" :items="fieldItems" item-text="name" item-value="value" @@ -270,12 +269,11 @@ export default { { name: 'False', value: false } ], fieldsResponse: null, - advancedSearchType: null, advancedSearchData: { - name: '', - internal_name: '', - id: '', - type: '' + name: null, + internal_name: null, + id: null, + type: null } } }, @@ -326,7 +324,7 @@ export default { return this.$store.state.databaseCount }, hideFields () { - const selectedOption = this.advancedSearchType + const selectedOption = this.advancedSearchData.type return { hideNameField: selectedOption === 'identifier', hideInternalNameField: ['identifier', 'user', 'concept', 'unit'].includes(selectedOption) @@ -377,19 +375,17 @@ export default { }) } }, - advancedSearchType: { - async handler () { - if (this.advancedSearchType) { - const promise = await SearchService.getFields(this.advancedSearchType.toLowerCase()) - this.fieldsResponse = JSON.parse(JSON.stringify(promise)) - console.log('Fields Response: ', this.fieldsResponse) - } else { - // Clear form fields from advancedSearchData if fields dropdown is cleared - for (const key in this.advancedSearchData) { - delete this.advancedSearchData[key] - } - this.fieldsResponse = null // Reset fieldsResponse when type is cleared from user + 'advancedSearchData.type': { + handler (newType, oldType) { + if (!newType) { + return } + console.debug('switched advanced search type to', newType) + this.resetAdvancedSearchFields() + SearchService.getFields(newType) + .then((response) => { + this.fieldsResponse = response + }) }, immediate: true } @@ -414,6 +410,12 @@ export default { submit () { this.$refs.form.validate() }, + /* Removes all advanced search fields when switching the type */ + resetAdvancedSearchFields () { + Object.keys(this.advancedSearchData) + .filter(k => !['name', 'internal_name', 'id', 'type'].includes(k)) + .forEach(k => delete this.advancedSearchData[k]) + }, login () { const redirect = ![undefined, '/', '/login'].includes(this.$router.currentRoute.path) this.$router.push({ path: '/login', query: redirect ? { redirect: this.$router.currentRoute.path } : {} }) @@ -487,6 +489,7 @@ export default { console.debug('runtime config', this.$config) }, advancedSearch () { + console.debug('performing advanced search') if (this.search) { this.advancedSearchData.search_term = this.search } else { @@ -500,7 +503,7 @@ export default { }, isAdvancedSearchEmpty () { return !( - this.advancedSearchType || + this.advancedSearchData.type || this.advancedSearchData.id || this.advancedSearchData.name || this.advancedSearchData.internal_name @@ -550,12 +553,12 @@ export default { // Generates a dynamic v-model; It will be attached to the advancedSearchData object if (!item) { return '' } - return `${this.advancedSearchType}.${item.attribute_name}` + return `${this.advancedSearchData.type}.${item.attribute_name}` }, shouldRenderItem (item) { // Checks if item's attribute_name matches any wanted field // The expected response is of a flattened format, so this method must be modified accordingly if the response is changed - return this.dynamicFieldsMap()[this.advancedSearchType].includes(item.attribute_name) + return this.dynamicFieldsMap()[this.advancedSearchData.type].includes(item.attribute_name) } }, head () { @@ -565,8 +568,7 @@ export default { }, provide () { return { - advancedSearchData: this.advancedSearchData, - advancedSearchType: this.advancedSearchType + advancedSearchData: this.advancedSearchData } } } diff --git a/dbrepo-ui/pages/search/index.vue b/dbrepo-ui/pages/search/index.vue index a62a788c0a26aba19a26a6cf9f6f95551948cd0f..ec8120ea70db8d1dab750c237b68a42584e04b43 100644 --- a/dbrepo-ui/pages/search/index.vue +++ b/dbrepo-ui/pages/search/index.vue @@ -37,7 +37,7 @@ import EventBus from '@/api/eventBus' import SearchService from '@/api/search.service' export default { - inject: ['advancedSearchData', 'advancedSearchType'], + inject: ['advancedSearchData'], data () { return { results: [], @@ -88,7 +88,7 @@ export default { }, created () { EventBus.$on('advancedSearchButtonClicked', () => { - this.doAdvancedSearch(this.advancedSearchType, this.advancedSearchData) + this.doAdvancedSearch(this.advancedSearchData) }) }, beforeDestroy () { @@ -96,7 +96,7 @@ export default { }, mounted () { if (Object.keys(this.advancedSearchData).some(key => key !== 'search_term')) { - this.doAdvancedSearch(this.advancedSearchType, this.advancedSearchData) + this.doAdvancedSearch(this.advancedSearchData) } else if (this.query) { this.retrieve(this.query) } @@ -107,7 +107,7 @@ export default { return } this.loading = true - SearchService.search(this.type, this.query, []) + SearchService.search(this.query) .then((hits) => { this.results = hits.map(h => h._source) }) @@ -115,9 +115,9 @@ export default { this.loading = false }) }, - doAdvancedSearch (advancedSearchType, advancedSearchData) { - console.debug('advanced search type:', advancedSearchType, 'data:', advancedSearchData) - SearchService.search(advancedSearchType, null, advancedSearchData) + doAdvancedSearch (advancedSearchData) { + console.debug('advanced search data:', advancedSearchData) + SearchService.search(advancedSearchData) .then((response) => { this.results = response.map(h => h._source) })