### Description

The [Terms Set Query](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-terms-set-query.html) lets you match documents that have some minimum number of matches to a given array of input search terms. The minimum number of matches however can only be specified by referencing another field on the document or by using a script.  

I have a use case where I need to be able to specify the minimum number of terms to match at query time, agnostic of documents so the `minimum_should_match_field` is not useful. Further, since I know I need to match a minimum of exactly, say, 3 terms, it seems like overkill to have to enable and using scripting (as in the use of `minimum_should_match_script`) to just return a static number.

Today as an alternative, I'm instead using a Bool Query with a `minimum_should_match` accepting my explicit number and all of my input search terms mapping to an array of individual `{ term: { field: value } }` entries in the `should` array of the bool. However, this is very json-inefficient, especially when I am making queries with many (possibly thousands) of terms in my query.

I was so happy to find the Terms Set query as a leaner, more specialized alternative to my massive `should` array but was then very surprised that there was no query-time input for the minimum match count (outside scripting).

**TL;DR:** Terms Set query should support a third possible top-level parameter for specifying the minimum number of terms to match which simply accepts a number, like `minimum_should_match`
server/src/main/java/org/elasticsearch/index/query/TermsSetQueryBuilder.java
for (Object value : values) {
            if (fieldType != null) {
                queries.add(fieldType.termQuery(value, context));
            } else {
                queries.add(new TermQuery(new Term(fieldName, BytesRefs.toBytesRef(value))));
            }
        }
        return queries;
    }
    private LongValuesSource createValuesSource(SearchExecutionContext context) {
        LongValuesSource longValuesSource;
        if (minimumShouldMatchField != null) {
            MappedFieldType msmFieldType = context.getFieldType(minimumShouldMatchField);
            if (msmFieldType == null) {
                throw new QueryShardException(context, "failed to find minimum_should_match field [" + minimumShouldMatchField + "]");
            }
            IndexNumericFieldData fieldData = context.getForField(msmFieldType, MappedFieldType.FielddataOperation.SEARCH);
            longValuesSource = new FieldValuesSource(fieldData);
        } else if (minimumShouldMatchScript != null) {
            TermsSetQueryScript.Factory factory = context.compile(minimumShouldMatchScript, TermsSetQueryScript.CONTEXT);
            Map<String, Object> params = new HashMap<>();
            params.putAll(minimumShouldMatchScript.getParams());
            params.put("num_terms", values.size());
            longValuesSource = new ScriptLongValueSource(minimumShouldMatchScript, factory.newFactory(params, context.lookup()));
        } else {
            throw new IllegalStateException("No minimum should match has been specified");
        }
        return longValuesSource;
    }
    static final class ScriptLongValueSource extends LongValuesSource {