Elasticsearch terms aggregation on a not analyzed field with filters

Since it is not_analyzed the query terms are case-sensitive. You could use multi-field mapping on city with analyzed and non-analyzed fields.

Example:

put <index>/<type>/_mapping
{
   "properties": {
      "city": {
         "type": "string",
         "fields": {
            "raw": {
               "type": "string",
               "index": "not_analyzed"
            }
         }
      }
   }
}

post <index>/<type>/_search
{
    "size": 0,
    "query": {
        "match_phrase_prefix": {
            "city": "Sao"
        }
    },
    "aggs": {
        "city": {
                "terms": {
                    "field": "city.raw"
                }
            }
    }
}