docs: private Map<String, Object> parseFacet(String facet) throws Exception {
          Map<String, Object> outputMap = new HashMap<>();
          if (facet.contains(AGGREGATION_IDENTIFIER)) {
              // Validate function
              for (String function : AGGREGATION_FUNCTIONS) {
                  if (facet.startsWith(function)) {
                      return null;
                  }
              }
              throw new Exception("Invalid aggregation function: " + facet);
          } else if (facet.contains(RANGE_IDENTIFIER)) {
              // Deal with ranges...
              int numMatches = StringUtils.countMatches(facet, ':');
              if (numMatches > 1) {
                  // Special case: facet with type "query" and with a nested "range"
                  String[] split = facet.split(":");
                  Map<String, Object> rangeMap = new HashMap<>();
                  StringBuilder filter = new StringBuilder(split[3]);
                  for (int i = 4; i < split.length; i++) {
                      filter.append(":").append(split[i]);
                  }
  
                  String[] range = split[0].replace("[", ":").replace("..", ":").replace("]", "").split(":");
                  rangeMap.put("field", range[0]);
                  rangeMap.put("type", "range");
                  rangeMap.put("start", parseNumber(range[1]));
                  rangeMap.put("end", parseNumber(range[2]));
                  rangeMap.put("step", parseNumber(split[1]));
  
                  String[] nested = split[2].split(LABEL_SEPARATOR);
                  outputMap.put("field", nested[0]);
                  outputMap.put("type", "query");
                  outputMap.put("q", filter.toString());
                  if (nested.length > 1) {
                      Map<String, Object> nestedMap = new HashMap<>();
                      nestedMap.put("field", nested[1]);
                      nestedMap.put("type", "terms");
                      Map<String, Object> auxMap1 = new HashMap<>();
                      auxMap1.put(range[0], rangeMap);
                      nestedMap.put("facet", auxMap1);
  
                      Map<String, Object> auxMap2 = new HashMap<>();
                      auxMap2.put(nested[1], nestedMap);
                      outputMap.put("facet", auxMap2);
                  } else {
                      Map<String, Object> auxMap1 = new HashMap<>();
                      auxMap1.put(range[0], rangeMap);
                      outputMap.put("facet", auxMap1);
                  }
              } else {
                  String[] split = facet.replace("[", ":").replace("..", ":").replace("]", "").split(":");
                  outputMap.put("field", split[0]);
                  outputMap.put("start", parseNumber(split[1]));
                  outputMap.put("end", parseNumber(split[2]));
                  outputMap.put("step", parseNumber(split[3]));
              }
          } else {
              // Categorical...
              Matcher matcher = CATEGORICAL_PATTERN.matcher(facet);
              if (matcher.find()) {
                  boolean isQuery = false;
                  outputMap.put("field", matcher.group(1));
                  String include = matcher.group(2);
                  if (StringUtils.isNotEmpty(include)) {
                      include = include.replace("]", "").replace("[", "");
                      if (include.endsWith("*")) {
                          outputMap.put("prefix", include.substring(0, include.indexOf("*")));
                      } else {
                          isQuery = true;
                          List<String> filters = new ArrayList<>();
                          for (String value: include.split(INCLUDE_SEPARATOR)) {
                              filters.add(matcher.group(1) + ":" + value);
                          }
                          outputMap.put("q", StringUtils.join(filters, " OR "));
                      }
                  }
  
                  if (isQuery) {
                      outputMap.put("type", "query");
  
                      Map<String, Object> auxMap = new HashMap<>();
                      auxMap.put("field", matcher.group(1));
                      auxMap.put("type", "terms");
                      setTermLimit(matcher.group(3), auxMap);
  
                      Map<String, Object> tmpMap = new HashMap<>();
                      tmpMap.put(matcher.group(1), auxMap);
  
                      outputMap.put("facet", tmpMap);
                  } else {
                      outputMap.put("type", "terms");
                      setTermLimit(matcher.group(3), outputMap);
                  }
              } else {
                  throw new Exception("Invalid categorical facet: " + facet);
              }
          }
  
          return outputMap;
      }