### Elasticsearch Version

Version: 8.7.1, Build: docker/f229ed3f893a515d590d0f39b05f68913e2d9b53/2023-04-27T04:33:42.127815583Z, JVM: 20.0.1

### Installed Plugins

_No response_

### Java Version

_bundled_

### OS Version

Linux f7ea544ab24a 5.15.49-linuxkit #1 SMP Tue Sep 13 07:51:46 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux

### Problem Description

Starting in 8.7.0, the lucene query constructed for `multi_match` queries of type `phrase_prefix` and multiple explicitly specified fields is wrong, only searching one filed multiple times instead of all specified fields once, resulting in incomplete search results. See next section for detailed steps and description of where it goes wrong.

### Steps to Reproduce

1. Create index
```
curl -X PUT "localhost:9200/people?pretty" -H 'Content-Type: application/json' -d'
{
  "settings": {
    "analysis": {
      "analyzer": {
        "default": {
          "type": "custom",
          "filter": [
            "lowercase",
            "asciifolding"
          ],
          "tokenizer": "whitespace"
        }
      }
    }
  },
  "mappings": {
    "dynamic_templates": [
      {
        "strings": {
          "match_mapping_type": "string",
          "mapping": {
            "type": "text",
            "fields": {
              "raw": {
                "type": "keyword"
              }
            },
            "index_prefixes": {
              "min_chars": 1,
              "max_chars": 19
            }
          }
        }
      }
    ]
  }
}
'
```
2. Add person to index
```
curl -X PUT "localhost:9200/people/_doc/1?pretty" -H 'Content-Type: application/json' -d'
{
  "first-name": "Harry",
  "last-name": "Potter",
  "email": "harry.potter@hogwarts.com",
  "identification": "01"
}
'
```
3. Search in all fields using `multi_match` and `phrase_prefix`, not find anything 🤔
```
curl -X GET "localhost:9200/people/_search?pretty" -H 'Content-Type: application/json' -d'
{
  "query": {
    "multi_match": {
      "query": "Har",
      "type": "phrase_prefix",
      "fields": [
        "first-name",
        "last-name",
        "email",
        "identification"
      ]
    }
  }
}
'
```
4. Show lucene query
```
curl -X GET "localhost:9200/people/_validate/query?rewrite=true" -H 'Content-Type: application/json' -d'
{
  "query": {
    "multi_match": {
      "query": "Har",
      "type": "phrase_prefix",
      "fields": [
        "first-name",
        "last-name",
        "email",
        "identification"
      ]
    }
  }
}
'
```
The resulting query searches the `identification` field four times. This is not right.
```
{
  "_shards": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "valid": true,
  "explanations": [
    {
      "index": "people",
      "valid": true,
      "explanation": "(identification._index_prefix:har | identification._index_prefix:har | identification._index_prefix:har | identification._index_prefix:har)"
    }
  ]
}
```
In ES 8.6.2 and older, the query searches all fields once.
```
{
  "_shards": {
    "total": 1,
    "successful": 1,
    "failed": 0
  },
  "valid": true,
  "explanations": [
    {
      "index": "people",
      "valid": true,
      "explanation": "(identification._index_prefix:har | first-name._index_prefix:har | last-name._index_prefix:har | email._index_prefix:har)"
    }
  ]
}
```

### Logs (if relevant)

_No response_
server/src/test/java/org/elasticsearch/index/query/MultiMatchQueryBuilderTests.java
hasItems(new TermQuery(new Term(TEXT_FIELD_NAME, "hello")), new TermQuery(new Term(KEYWORD_FIELD_NAME, "hello")))
        );
    }
    /**
     * "now" on date fields should make the query non-cachable.
     */
    public void testCachingStrategiesWithNow() throws IOException {
        
        MultiMatchQueryBuilder queryBuilder = new MultiMatchQueryBuilder("now", DATE_FIELD_NAME);
        SearchExecutionContext context = createSearchExecutionContext();
        assert context.isCacheable();
        /*
         * We use a private rewrite context here since we want the most realistic way of asserting that we are cacheable or not. We do it
         * this way in SearchService where we first rewrite the query with a private context, then reset the context and then build the
         * actual lucene query
         */
        QueryBuilder rewritten = rewriteQuery(queryBuilder, new SearchExecutionContext(context));
        assertNotNull(rewritten.toQuery(context));
        assertFalse("query should not be cacheable: " + queryBuilder.toString(), context.isCacheable());
    }
    public void testLenientFlag() throws Exception {
        MultiMatchQueryBuilder query = new MultiMatchQueryBuilder("test", BINARY_FIELD_NAME);
        SearchExecutionContext context = createSearchExecutionContext();
        IllegalArgumentException e = expectThrows(IllegalArgumentException.class, () -> query.toQuery(context));
        assertEquals("Field [mapped_binary] of type [binary] does not support match queries", e.getMessage());
        query.lenient(true);
        assertThat(query.toQuery(context), Matchers.instanceOf(MatchNoDocsQuery.class));
    }
}