private Query getTermQuery(final ExpressionTerm term,
                               final Set<String> terms) {
        String field = term.getField();
        final Condition condition = term.getCondition();
        String value = term.getValue();
        final DocRef docRef = term.getDocRef();

        // Clean strings to remove unwanted whitespace that the user may have
        // added accidentally.
        if (field != null) {
            field = field.trim();
        }
        if (value != null) {
            value = value.trim();
        }

        // Try and find the referenced field.
        if (field == null || field.isEmpty()) {
            throw new SearchException("Field not set");
        }
        final IndexField indexField = indexFieldCache.get(indexDocRef, field);
        if (indexField == null) {
            // Ignore missing fields.
            return null;
//            throw new SearchException("Field not found in index: " + field);
        }
        final String fieldName = indexField.getFldName();

        // Ensure an appropriate value has been provided for the condition type.
        if (Condition.IN_DICTIONARY.equals(condition)) {
            if (docRef == null || docRef.getUuid() == null) {
                throw new SearchException("Dictionary not set for field: " + field);
            }
        } else if (Condition.IS_DOC_REF.equals(condition)) {
            if (docRef == null || docRef.getUuid() == null) {
                throw new SearchException("Doc Ref not set for field: " + field);
            }
        } else {
            if (value == null || value.isEmpty()) {
                return null;
            }
        }

        // Create a query based on the field type and condition.
        if (indexField.getFldType().isNumeric()) {
            switch (condition) {
                case EQUALS -> {
                    final Long num1 = getNumber(fieldName, value);
                    return NumericRangeQuery.newLongRange(
                            fieldName, num1, num1, true, true);
                }
                case NOT_EQUALS -> {
                    final Long num1 = getNumber(fieldName, value);
                    return negate(NumericRangeQuery.newLongRange(
                            fieldName, num1, num1, true, true));
                }
                case CONTAINS -> {
                    return getContains(fieldName, value, indexField, terms);
                }
                case GREATER_THAN -> {
                    return NumericRangeQuery.newLongRange(
                            fieldName, getNumber(fieldName, value), Long.MAX_VALUE, false,
                            true);
                }
                case GREATER_THAN_OR_EQUAL_TO -> {
                    return NumericRangeQuery.newLongRange(
                            fieldName, getNumber(fieldName, value), Long.MAX_VALUE, true,
                            true);
                }
                case LESS_THAN -> {
                    return NumericRangeQuery.newLongRange(
                            fieldName, Long.MIN_VALUE, getNumber(fieldName, value), true,
                            false);
                }
                case LESS_THAN_OR_EQUAL_TO -> {
                    return NumericRangeQuery.newLongRange(
                            fieldName, Long.MIN_VALUE, getNumber(fieldName, value), true,
                            true);
                }
                case BETWEEN -> {
                    final long[] between = getNumbers(fieldName, value);
                    if (between.length != 2) {
                        throw new SearchException("2 numbers needed for between query");
                    }
                    if (between[0] >= between[1]) {
                        throw new SearchException("From number must lower than to number");
                    }
                    return NumericRangeQuery.newLongRange(
                            fieldName, between[0], between[1], true, true);
                }
                case IN -> {
                    return getNumericIn(fieldName, value);
                }
                case IN_DICTIONARY -> {
                    return getDictionary(fieldName, docRef, indexField, terms);
                }
                default -> throw new SearchException("Unexpected condition '" + condition.getDisplayValue() + "' for "
                        + indexField.getFldType().getDisplayValue() + " field type");
            }
        } else if (FieldType.DATE.equals(indexField.getFldType())) {
            switch (condition) {
                case EQUALS -> {
                    final Long date1 = DateExpressionParser.getMs(fieldName, value, dateTimeSettings);
                    return NumericRangeQuery.newLongRange(fieldName, date1, date1, true, true);
                }
                case NOT_EQUALS -> {
                    final Long date1 = DateExpressionParser.getMs(fieldName, value, dateTimeSettings);
                    return negate(NumericRangeQuery.newLongRange(fieldName, date1, date1, true, true));
                }
                case CONTAINS -> {
                    return getContains(fieldName, value, indexField, terms);
                }
                case GREATER_THAN -> {
                    return NumericRangeQuery.newLongRange(fieldName,
                            8,
                            DateExpressionParser.getMs(fieldName, value, dateTimeSettings),
                            Long.MAX_VALUE,
                            false,
                            true);
                }
                case GREATER_THAN_OR_EQUAL_TO -> {
                    return NumericRangeQuery.newLongRange(
                            fieldName,
                            8,
                            DateExpressionParser.getMs(fieldName, value, dateTimeSettings),
                            Long.MAX_VALUE,
                            true,
                            true);
                }
                case LESS_THAN -> {
                    return NumericRangeQuery.newLongRange(
                            fieldName,
                            8,
                            Long.MIN_VALUE,
                            DateExpressionParser.getMs(fieldName, value, dateTimeSettings),
                            true,
                            false);
                }
                case LESS_THAN_OR_EQUAL_TO -> {
                    return NumericRangeQuery.newLongRange(
                            fieldName,
                            8,
                            Long.MIN_VALUE,
                            DateExpressionParser.getMs(fieldName, value, dateTimeSettings),
                            true,
                            true);
                }
                case BETWEEN -> {
                    final long[] between = getDates(fieldName, value);
                    if (between.length != 2) {
                        throw new SearchException("2 dates needed for between query");
                    }
                    if (between[0] >= between[1]) {
                        throw new SearchException("From date must occur before to date");
                    }
                    return NumericRangeQuery.newLongRange(
                            fieldName, 8, between[0], between[1], true, true);
                }
                case IN -> {
                    return getDateIn(fieldName, value);
                }
                case IN_DICTIONARY -> {
                    return getDictionary(fieldName, docRef, indexField, terms);
                }
                default -> throw new SearchException("Unexpected condition '" + condition.getDisplayValue() + "' for "
                        + indexField.getFldType().getDisplayValue() + " field type");
            }
        } else {
            return switch (condition) {
                case EQUALS -> getContains(fieldName, value, indexField, terms);
                case NOT_EQUALS -> negate(getContains(fieldName, value, indexField, terms));
//                    return getSubQuery(matchVersion, indexField, value, terms, false);
                case CONTAINS -> getContains(fieldName, value, indexField, terms);
                case IN -> getIn(fieldName, value, indexField, terms);
                case IN_DICTIONARY -> getDictionary(fieldName, docRef, indexField, terms);
                case IS_DOC_REF -> getSubQuery(indexField, docRef.getUuid(), terms, false);
                default -> throw new SearchException("Unexpected condition '" + condition.getDisplayValue() + "' for "
                        + indexField.getFldType().getDisplayValue() + " field type");
            };
        }
    }
Convert our query objects to a LUCENE query.
stroom-search/stroom-search-solr/src/main/java/stroom/search/solr/search/SearchExpressionQueryBuilder.java