private Query buildScalarQuery(
            final ExpressionTerm.Condition condition,
            final ElasticIndexField indexField,
            final String fieldName,
            final String rawValue,
            final TriFunction<Condition, String, String, FieldValue> valueParser,
            final DocRef docRef
    ) {
        FieldValue fieldValue;
        List<FieldValue> fieldValues;

        switch (condition) {
            case EQUALS -> {
                fieldValue = valueParser.apply(condition, fieldName, rawValue);
                return QueryBuilders
                        .term(q -> q
                                .field(fieldName)
                                .value(fieldValue));
            }
            case NOT_EQUALS -> {
                fieldValue = valueParser.apply(condition, fieldName, rawValue);
                return negate(QueryBuilders
                        .term(q -> q
                                .field(fieldName)
                                .value(fieldValue)));
            }
            case IN -> {
                fieldValues = tokenizeExpression(rawValue)
                        .map(val -> valueParser.apply(condition, fieldName, val))
                        .toList();
                return QueryBuilders
                        .terms(q -> q
                                .field(fieldName)
                                .terms(t -> t.value(fieldValues)));
            }
            case GREATER_THAN -> {
                fieldValue = valueParser.apply(condition, fieldName, rawValue);
                return QueryBuilders
                        .range(q -> q
                                .field(fieldName)
                                .gt(JsonData.of(fieldValue)));
            }
            case GREATER_THAN_OR_EQUAL_TO -> {
                fieldValue = valueParser.apply(condition, fieldName, rawValue);
                return QueryBuilders
                        .range(q -> q
                                .field(fieldName)
                                .gte(JsonData.of(fieldValue)));
            }
            case LESS_THAN -> {
                fieldValue = valueParser.apply(condition, fieldName, rawValue);
                return QueryBuilders
                        .range(q -> q
                                .field(fieldName)
                                .lt(JsonData.of(fieldValue)));
            }
            case LESS_THAN_OR_EQUAL_TO -> {
                fieldValue = valueParser.apply(condition, fieldName, rawValue);
                return QueryBuilders
                        .range(q -> q
                                .field(fieldName)
                                .lte(JsonData.of(fieldValue)));
            }
            case BETWEEN -> {
                fieldValues = tokenizeExpression(rawValue)
                        .map(val -> valueParser.apply(condition, fieldName, val))
                        .toList();
                if (fieldValues.size() != 2) {
                    throw new IllegalArgumentException(
                            "Two values needed for between query. Only " + fieldValues.size() + " provided");
                }
                return QueryBuilders
                        .range(q -> q
                                .field(fieldName)
                                .gte(JsonData.of(fieldValues.get(0)))
                                .lte(JsonData.of(fieldValues.get(1))));
            }
            case IN_DICTIONARY -> {
                return buildDictionaryQuery(condition, fieldName, docRef, indexField);
            }
            default -> throw new SearchException("Unexpected condition '" + condition.getDisplayValue() + "' for " +
                    indexField.getFldType().getDisplayValue() + " field type");
        }
    }
Creates an Elasticsearch query for a `keyword` field appropriate for the expression content
stroom-search/stroom-search-elastic/src/main/java/stroom/search/elastic/search/SearchExpressionQueryBuilder.java