appbaseio / appbaseio/reactivesearch
Unable to use multi-select and its giving error
- Vorherrschende Sprache
- JavaScript
- Sterne
- 4.9k
- Forks
- 477
- PR-Merge-Kennzahlen
- Keine gemergten PRs in 30 T.
Beschreibung
**Affected Projects**
Vue.JS
**Library Version:** x.y.z
"@appbaseio/reactivesearch-vue": "3.1.0-alpha.1",
**Describe the bug**
I am migrating our app from vue 2 to vue 3, so also need to migrate appbase. there is is migration docs which we following. everything seems work but when we filter it gives this error
```
bugsnag.js:2688 {"settings":{"took":6,"searchTook":2},"SearchResults":{"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [email] in order to load field data by uninverting the inverted index. Note that this can use significant memory."}],"type":"search_phase_execution_exception","reason":"all shards failed","phase":"query","grouped":true,"failed_shards":[{"shard":0,"index":"4760d3c8-ab04-450d-b83c-83ff9bdc1d0d","node":"Fa2quZrSSlCuIwgA2TZRVg","reason":{"type":"illegal_argument_exception","reason":"Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [email] in order to load field data by uninverting the inverted index. Note that this can use significant memory."}}],"caused_by":{"type":"illegal_argument_exception","reason":"Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [email] in order to load field data by uninverting the inverted index. Note that this can use significant memory.","caused_by":{"type":"illegal_argument_exception","reason":"Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [email] in order to load field data by uninverting the inverted index. Note that this can use significant memory."}}},"status":400}}
console. @ bugsnag.js:2688
handleError @ utils.js:1
eval @ query.js:1
```
**Desktop (please complete the following information):**
- Browser [e.g. chrome]
here is my component code
```
{{ header.text }}
{{ $store.state.registration.roleNames[label] }}
{{ label }}
import MagnifyingGlass from '@/studioComponents/Icons/MagnifyingGlass.vue';
import Funnel from '@/studioComponents/Icons/Funnel.vue';
import { mapGetters, mapMutations, mapState } from 'vuex';
export default {
name: 'StudioRegistrantsTableHeader',
components: { MagnifyingGlass, Funnel },
props: {
headers: {
type: Array,
default: () => []
}
},
data() {
const headerPopups = this.headers
.map(it => it.value)
.reduce((acuum, item) => {
acuum[item] = false;
return acuum;
}, {});
return {
headerPopups
};
},
computed: {
...mapState('registration', ['allSelected', 'lastSearchedQueryResultSize']),
...mapGetters('registration', ['numSelected'])
},
methods: {
...mapMutations('registration', ['toggleSelectAll']),
toggleColumnSelected() {
this.toggleSelectAll(!this.allSelected);
}
}
};
.inlineSearch {
#full_name-downshift {
height: 160px;
}
#email-downshift {
height: 160px;
}
}
.v-menu__content {
background: white;
}
```
Parent component
```
Register attendees for your event and control access for each user. Registrants will automatically be sent email
notifications once added, so confirm your email schedule before uploading registrants.
{{ summary }}
Clear All Filters
No registrants yet!
import { mapState, mapActions, mapGetters, mapMutations } from 'vuex';
import StudioRegistrantsTableRow from './StudioRegistrantsTableRow.vue';
import StudioRegistrantsTableHeader from './StudioRegistrantsTableHeader.vue';
import StudioRegistrantsActions from './StudioRegistrantsActions.vue';
import StudioRegistrantsColumnSelectionPopup from './StudioRegistrantsColumnSelectionPopup.vue';
import StudioAddRegistrant from './StudioAddRegistrant.vue';
import { snakeCaseToCapitalized } from '@/store/modules/registration';
import LogRocket from 'logrocket';
import StudioButton from '@/studioComponents/StudioButton.vue';
import StudioPageIntro from '@/studioComponents/StudioPageIntro.vue';
import StudioSpinner from '@/studioComponents/StudioSpinner.vue';
import Chip from '@/commonComponents/Chip.vue';
import throttle from 'lodash.throttle';
import Refresh from '@/studioComponents/Icons/Refresh.vue';
import { VDataTable } from 'vuetify/labs/VDataTable';
export default {
name: 'StudioRegistrantsWrapper',
components: {
StudioRegistrantsTableHeader,
StudioRegistrantsTableRow,
StudioRegistrantsActions,
StudioRegistrantsColumnSelectionPopup,
StudioAddRegistrant,
Chip,
StudioButton,
StudioSpinner,
StudioPageIntro,
Refresh,
VDataTable
},
computed: {
...mapState('registration', {
appBaseUrl: 'appBaseUrl',
loadingRegistration: 'loadingRegistration',
appbaseError: 'appbaseError',
columns: 'columns',
roleNames: 'roleNames',
lastSearchedQueryResultSize: 'lastSearchedQueryResultSize'
}),
...mapGetters('registration', ['visibleColumns']),
...mapGetters('studioEventList', {
event: 'getCurrentEvent'
}),
appbaseCredentials() {
return this.event?.appbase_credentials;
},
selectedFilterValue() {
return (componentId, selectedValues) => {
if (componentId === 'role') {
return selectedValues[componentId].value
.map(role => {
return this.roleNames[role];
})
.join(',');
}
const value = selectedValues[componentId].value;
if (Array.isArray(value)) {
return value.join(',');
}
return value;
};
},
oredFilters() {
const ored = this.columns
.map(it => it.value)
.filter(it => {
return !['user__magic_link', 'id', 'event_id', 'profile_picture_url'].includes(it);
});
return ored.concat('SearchUsers').concat('role');
},
eventId() {
return this.$route.params.eventId;
},
summary() {
if (this.loadingRegistration) {
return '';
}
if (this.lastSearchedQueryResultSize <= 0) {
return '';
}
if (this.lastSearchedQueryResultSize === 1) {
return '1 Registrant';
}
return `${this.lastSearchedQueryResultSize} Registrants`;
}
},
data() {
return {
loadingColumns: true,
currentPage: 1,
sortOptions: [
{
label: 'Full Name ↑',
dataField: 'full_name.keyword',
sortBy: 'asc'
},
{
label: 'Full Name ↓',
dataField: 'full_name.keyword',
sortBy: 'desc'
},
{
label: 'Email ↑',
dataField: 'email.keyword',
sortBy: 'asc'
},
{
label: 'Email ↓',
dataField: 'email.keyword',
sortBy: 'desc'
},
{
label: 'Date Registered ↑',
dataField: 'date_registered.keyword',
sortBy: 'asc'
},
{
label: 'Date Registered ↓',
dataField: 'date_registered.keyword',
sortBy: 'desc'
}
]
};
},
mounted() {
this.fetchColumns().then(() => {
this.loadingColumns = false;
});
this.fetchEventMembers({ eventId: this.eventId });
},
beforeRouteLeave(to, from, next) {
this.toggleSelectAll(false);
this.toggleColumnPopup(false);
this.setSelectedQuery(null);
next();
},
methods: {
...mapActions('registration', ['fetchColumns']),
...mapActions('eventList', ['getEventMembers', 'blockEventBulkUser']),
...mapActions('studioEventList', ['fetchEventMembers']),
...mapMutations('registration', [
'toggleSelectAll',
'toggleColumnPopup',
'setSelectedQuery',
'setLoadingRegistration',
'storeAppbaseQueryDSL',
'toggleSelection'
]),
// This cannot be a computed property because it is inside the render
// function of appbase and hence cannot know when to recompute unless
// its passed as a method
handleBanFinished({ timeout }) {
this.toggleSelectAll(false);
this.searchRegistrants();
// The banned data doesn't reflect in appbase immediately so wait to refresh
setTimeout(() => {
this.refreshList();
}, timeout);
},
refreshList: throttle(function () {
const datalist = this.$refs.datalist;
if (datalist) {
this.setLoadingRegistration(true);
if (!this.columns?.length) {
this.fetchColumns();
}
const currentPage = datalist.$el.__vue__.currentPageState;
datalist.$el.__vue__.setPage(currentPage + 1);
setTimeout(() => {
datalist.$el.__vue__.setPage(currentPage);
this.setLoadingRegistration(false);
}, 100);
} else {
LogRocket.info('Could not refresh by page change because reactivebase was not found!');
}
}, 2000),
filteredText(componentId) {
return this.snakeCaseToCapitalized(componentId === 'blocked' ? 'banned' : componentId);
},
onQueryChange(prev, next) {
LogRocket.info('Query change: ', prev, next);
this.storeAppbaseQueryDSL({
next,
numResults: -1
});
},
onResult(payload) {
const numResults = payload.resultStats.numberOfResults;
LogRocket.info('Number of results in appbase query: ' + numResults);
this.storeAppbaseQueryDSL({
numResults
});
},
searchRegistrants() {
if (this.currentPage == 1) {
this.fetchEventMembers({ eventId: this.event.id });
} else {
this.currentPage = 1;
}
},
snakeCaseToCapitalized,
getFilteredValues(values = {}) {
const filteredValues = {};
Object.keys(values).forEach(componentId => {
if (
values[componentId].showFilter &&
(Array.isArray(values[componentId].value) ? values[componentId].value.length : !!values[componentId].value)
) {
filteredValues[componentId] = values[componentId];
}
});
return filteredValues;
},
defaultQuery() {
return {
track_total_hits: true,
query: { match_all: {} }
};
},
singleItemSelectionHandler(row) {
this.toggleSelection(row);
}
}
};
// This block is for modifying appbase css
// Do not scope it
.appbase-search {
& #SearchUsers-input {
font-size: 14px;
min-height: 0;
border-radius: 999px;
border-color: rgb(209 213 219);
background-color: white;
&:focus {
border-color: rgb(135 128 253);
}
}
& svg.search-icon[alt='Search'] {
fill: #222;
height: 12px;
width: 12px;
}
}
.search-bar-list {
border: 1px solid rgb(209 213 219) !important;
max-height: 160px !important;
margin-top: 2px !important;
border-radius: 0.25rem !important;
}
select.appbase-sort-options {
position: absolute;
right: 2px;
top: 8px;
width: 160px;
border-radius: 0.25rem;
cursor: pointer;
&:hover {
border-color: rgb(135 128 253);
outline-color: rgb(135 128 253);
}
&:focus {
border-color: rgb(135 128 253);
outline: 2px solid rgb(135 128 253);
outline-offset: 0px;
}
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
background-position: right 0.5rem center;
background-repeat: no-repeat;
background-size: 1.5em 1.5em;
padding-right: 2.5rem;
-webkit-print-color-adjust: exact;
print-color-adjust: exact;
}
.content {
& .appbase-paginator {
text-align: center;
& > button {
font-family: 'Inter var', sans-serif;
&.active {
background-color: rgb(135 128 253);
color: white;
}
}
& > a {
color: rgba(28, 30, 31, 0.6);
background-color: transparent;
&.active {
color: white;
background: rgba(28, 30, 31, 0.6);
}
&:focus {
outline: none;
}
}
}
& .appbase-noresults {
display: none;
}
}
```
Beitragsleitfaden
Rechercherichtung
Beginne mit dem bereitgestellten registrants-Header und der übergeordneten Komponente und konzentriere dich auf die multi-list- und data-search-Steuerelemente für das email-Feld. Untersuche den Stack Trace von query.js und reproduziere die Filteranfrage, um zu ermitteln, warum die generierte Abfrage eine nicht unterstützte Operation für email ausführt. Als erledigt gilt die Aufgabe, wenn die multi-select-Filterung nicht mehr den gezeigten Elasticsearch-400-Fehler zurückgibt.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- elasticsearch, javascript
- Bereich
- frontend, search
- Issue-Typ
- Bug
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Veraltet
- Klarheit
- Muss geklärt werden
- Anfängerfreundlichkeit
- 25/100