public SearchQuery parse(String encodedQueryString) {
        if (Strings.isNullOrEmpty(encodedQueryString) || "*".equals(encodedQueryString)) {
            return new SearchQuery(encodedQueryString);
        }

        final var queryString = URLDecoder.decode(encodedQueryString, StandardCharsets.UTF_8);

        final Matcher matcher = querySplitterMatcher(requireNonNull(queryString).trim());
        final ImmutableMultimap.Builder<String, FieldValue> builder = ImmutableMultimap.builder();
        final ImmutableSet.Builder<String> disallowedKeys = ImmutableSet.builder();

        while (matcher.find()) {
            final String entry = matcher.group();

            if (!entry.contains(":")) {
                builder.put(withPrefixIfNeeded(defaultField), createFieldValue(defaultFieldKey.getFieldType(), entry, false));
                continue;
            }

            final Iterator<String> entryFields = FIELD_VALUE_SPLITTER.splitToList(entry).iterator();

            checkArgument(entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
            final String key = entryFields.next();

            // Skip if there are no valid k/v pairs. (i.e. "action:")
            if (!entryFields.hasNext()) {
                continue;
            }

            final boolean negate = key.startsWith("-");
            final String cleanKey = key.replaceFirst("^-", "");
            final String value = entryFields.next();
            VALUE_SPLITTER.splitToList(value).forEach(v -> {
                if (!dbFieldMapping.containsKey(cleanKey)) {
                    disallowedKeys.add(cleanKey);
                }
                final SearchQueryField translatedKey = dbFieldMapping.get(cleanKey);
                if (translatedKey != null) {
                    builder.put(withPrefixIfNeeded(translatedKey.getDbField()), createFieldValue(translatedKey.getFieldType(), v, negate));
                } else {
                    builder.put(withPrefixIfNeeded(defaultField), createFieldValue(defaultFieldKey.getFieldType(), v, negate));
                }
            });

            checkArgument(!entryFields.hasNext(), INVALID_ENTRY_MESSAGE, entry);
        }

        return new SearchQuery(queryString, builder.build(), disallowedKeys.build());
    }
@Test
    void booleanValuesSupported() {
        final SearchQueryParser parser = new SearchQueryParser("name",
                Map.of(
                        "name", SearchQueryField.create("title", SearchQueryField.Type.STRING),
                        "gone", SearchQueryField.create("disabled", SearchQueryField.Type.BOOLEAN)
                )
        );

        final SearchQuery searchQuery = parser.parse("gone:true");

        assertEquals("gone:true", searchQuery.getQueryString());
        final Multimap<String, SearchQueryParser.FieldValue> queryMap = searchQuery.getQueryMap();

        assertThat(queryMap.keySet().size()).isEqualTo(1);
        assertThat(queryMap.keySet()).containsOnly("disabled"); //properly renamed
        assertThat(queryMap.get("disabled"))
                .containsOnly(new SearchQueryParser.FieldValue(
                        true, //boolean true instead of "true" string!
                        SearchQueryOperators.EQUALS, //equals instead of reqexp!
                        false)
                );

    }