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) {
            return new MatchNoDocsQuery();
        }
        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 (FieldType.INTEGER.equals(indexField.getFldType())) {
            switch (condition) {
                case EQUALS -> {
                    final int num1 = getInt(fieldName, value);
                    return IntField.newExactQuery(fieldName, num1);
                }
                case NOT_EQUALS -> {
                    final int num1 = getInt(fieldName, value);
                    return negate(IntField.newExactQuery(fieldName, num1));
                }
                case CONTAINS -> {
                    return getContains(fieldName, value, indexField, terms);
                }
                case GREATER_THAN -> {
                    return IntField.newRangeQuery(fieldName, getInt(fieldName, value) + 1, Integer.MAX_VALUE);
                }
                case GREATER_THAN_OR_EQUAL_TO -> {
                    return IntField.newRangeQuery(fieldName, getInt(fieldName, value), Integer.MAX_VALUE);
                }
                case LESS_THAN -> {
                    return IntField.newRangeQuery(fieldName, Integer.MIN_VALUE, getInt(fieldName, value) - 1);
                }
                case LESS_THAN_OR_EQUAL_TO -> {
                    return IntField.newRangeQuery(fieldName, Integer.MIN_VALUE, getInt(fieldName, value));
                }
                case BETWEEN -> {
                    final int[] between = getInts(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 IntField.newRangeQuery(fieldName, between[0], between[1]);
                }
                case IN -> {
                    return getIntIn(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.LONG.equals(indexField.getFldType())) {
            switch (condition) {
                case EQUALS -> {
                    final long num1 = getLong(fieldName, value);
                    return LongField.newExactQuery(fieldName, num1);
                }
                case NOT_EQUALS -> {
                    final long num1 = getLong(fieldName, value);
                    return negate(LongField.newExactQuery(fieldName, num1));
                }
                case CONTAINS -> {
                    return getContains(fieldName, value, indexField, terms);
                }
                case GREATER_THAN -> {
                    return LongField.newRangeQuery(fieldName, getLong(fieldName, value) + 1, Long.MAX_VALUE);
                }
                case GREATER_THAN_OR_EQUAL_TO -> {
                    return LongField.newRangeQuery(fieldName, getLong(fieldName, value), Long.MAX_VALUE);
                }
                case LESS_THAN -> {
                    return LongField.newRangeQuery(fieldName, Long.MIN_VALUE, getLong(fieldName, value) - 1);
                }
                case LESS_THAN_OR_EQUAL_TO -> {
                    return LongField.newRangeQuery(fieldName, Long.MIN_VALUE, getLong(fieldName, value));
                }
                case BETWEEN -> {
                    final long[] between = getLongs(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 LongField.newRangeQuery(fieldName, between[0], between[1]);
                }
                case IN -> {
                    return getLongIn(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.FLOAT.equals(indexField.getFldType())) {
            switch (condition) {
                case EQUALS -> {
                    final float num1 = getFloat(fieldName, value);
                    return FloatField.newExactQuery(fieldName, num1);
                }
                case NOT_EQUALS -> {
                    final float num1 = getFloat(fieldName, value);
                    return negate(FloatField.newExactQuery(fieldName, num1));
                }
                case CONTAINS -> {
                    return getContains(fieldName, value, indexField, terms);
                }
                case GREATER_THAN -> {
                    return FloatField.newRangeQuery(fieldName,
                            getFloat(fieldName, value) + Float.MIN_VALUE,
                            Float.MAX_VALUE);
                }
                case GREATER_THAN_OR_EQUAL_TO -> {
                    return FloatField.newRangeQuery(fieldName, getFloat(fieldName, value), Float.MAX_VALUE);
                }
                case LESS_THAN -> {
                    return FloatField.newRangeQuery(fieldName, Float.MIN_VALUE, getFloat(fieldName, value)
                            - Float.MIN_VALUE);
                }
                case LESS_THAN_OR_EQUAL_TO -> {
                    return FloatField.newRangeQuery(fieldName, Float.MIN_VALUE, getFloat(fieldName, value));
                }
                case BETWEEN -> {
                    final float[] between = getFloats(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 FloatField.newRangeQuery(fieldName, between[0], between[1]);
                }
                case IN -> {
                    return getFloatIn(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.DOUBLE.equals(indexField.getFldType())) {
            switch (condition) {
                case EQUALS -> {
                    final double num1 = getDouble(fieldName, value);
                    return DoubleField.newExactQuery(fieldName, num1);
                }
                case NOT_EQUALS -> {
                    final double num1 = getDouble(fieldName, value);
                    return negate(DoubleField.newExactQuery(fieldName, num1));
                }
                case CONTAINS -> {
                    return getContains(fieldName, value, indexField, terms);
                }
                case GREATER_THAN -> {
                    return DoubleField.newRangeQuery(fieldName,
                            getDouble(fieldName, value) + Double.MIN_VALUE,
                            Double.MAX_VALUE);
                }
                case GREATER_THAN_OR_EQUAL_TO -> {
                    return DoubleField.newRangeQuery(fieldName,
                            getDouble(fieldName, value),
                            Double.MAX_VALUE);
                }
                case LESS_THAN -> {
                    return DoubleField.newRangeQuery(fieldName,
                            Double.MIN_VALUE,
                            getDouble(fieldName, value) - Double.MIN_VALUE);
                }
                case LESS_THAN_OR_EQUAL_TO -> {
                    return DoubleField.newRangeQuery(fieldName,
                            Double.MIN_VALUE,
                            getDouble(fieldName, value));
                }
                case BETWEEN -> {
                    final double[] between = getDoubles(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 DoubleField.newRangeQuery(fieldName, between[0], between[1]);
                }
                case IN -> {
                    return getDoubleIn(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 = getDate(fieldName, value);
                    return LongField.newExactQuery(fieldName, date1);
                }
                case NOT_EQUALS -> {
                    final long date1 = getDate(fieldName, value);
                    return negate(LongField.newExactQuery(fieldName, date1));
                }
                case CONTAINS -> {
                    return getContains(fieldName, value, indexField, terms);
                }
                case GREATER_THAN -> {
                    return LongField.newRangeQuery(fieldName,
                            getDate(fieldName, value) + 1,
                            Long.MAX_VALUE);
                }
                case GREATER_THAN_OR_EQUAL_TO -> {
                    return LongField.newRangeQuery(fieldName, getDate(fieldName, value), Long.MAX_VALUE);
                }
                case LESS_THAN -> {
                    return LongField.newRangeQuery(fieldName, Long.MIN_VALUE, getDate(fieldName, value) - 1);
                }
                case LESS_THAN_OR_EQUAL_TO -> {
                    return LongField.newRangeQuery(fieldName, Long.MIN_VALUE, getDate(fieldName, value));
                }
                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 LongField.newRangeQuery(fieldName, between[0], between[1]);
                }
                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 if (indexField.getFldType().isNumeric()) {
            switch (condition) {
                case EQUALS -> {
                    final long num1 = getLong(fieldName, value);
                    return LongField.newExactQuery(fieldName, num1);
                }
                case NOT_EQUALS -> {
                    final long num1 = getLong(fieldName, value);
                    return negate(LongField.newExactQuery(fieldName, num1));
                }
                case CONTAINS -> {
                    return getContains(fieldName, value, indexField, terms);
                }
                case GREATER_THAN -> {
                    return LongField.newRangeQuery(fieldName, getLong(fieldName, value) + 1, Long.MAX_VALUE);
                }
                case GREATER_THAN_OR_EQUAL_TO -> {
                    return LongField.newRangeQuery(fieldName, getLong(fieldName, value), Long.MAX_VALUE);
                }
                case LESS_THAN -> {
                    return LongField.newRangeQuery(fieldName, Long.MIN_VALUE, getLong(fieldName, value) - 1);
                }
                case LESS_THAN_OR_EQUAL_TO -> {
                    return LongField.newRangeQuery(fieldName, Long.MIN_VALUE, getLong(fieldName, value));
                }
                case BETWEEN -> {
                    final long[] between = getLongs(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 LongField.newRangeQuery(fieldName, between[0], between[1]);
                }
                case IN -> {
                    return getLongIn(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-index/stroom-index-lucene980/src/main/java/stroom/index/lucene980/SearchExpressionQueryBuilder.java