algoliasearch/src/main/java/com/algolia/search/saas/helpers/DisjunctiveFaceting.java
static private @NonNull <T extends Collection<String>> List<Query> computeDisjunctiveFacetingQueries(@NonNull Query query, @NonNull Collection<String> disjunctiveFacets, @NonNull Map<String, T> refinements) {
        // Retain only refinements corresponding to the disjunctive facets.
        Map<String, ? extends Collection<String>> disjunctiveRefinements = filterDisjunctiveRefinements(disjunctiveFacets, refinements);

        // build queries
        List<Query> queries = new ArrayList<>();

        // first query: hits + regular facets
        JSONArray facetFilters = new JSONArray();
        for (Map.Entry<String, T> elt : refinements.entrySet()) {
            JSONArray orFilters = new JSONArray();

            for (String val : elt.getValue()) {
                // When already refined facet, or with existing refinements
                if (disjunctiveRefinements.containsKey(elt.getKey())) {
                    orFilters.put(formatFilter(elt, val));
                } else {
                    facetFilters.put(formatFilter(elt, val));
                }
            }
            // Add or
            if (disjunctiveRefinements.containsKey(elt.getKey())) {
                facetFilters.put(orFilters);
            }
        }

        //noinspection deprecation Deprecated for end-users
        queries.add(new Query(query).setFacetFilters(facetFilters));
        // one query per disjunctive facet (use all refinements but the current one + hitsPerPage=1 + single facet
        for (String disjunctiveFacet : disjunctiveFacets) {
            facetFilters = new JSONArray();
            for (Map.Entry<String, T> elt : refinements.entrySet()) {
                if (disjunctiveFacet.equals(elt.getKey())) {
                    continue;
                }
                JSONArray orFilters = new JSONArray();
                for (String val : elt.getValue()) {
                    if (disjunctiveRefinements.containsKey(elt.getKey())) {
                        orFilters.put(formatFilter(elt, val));
                    } else {
                        facetFilters.put(formatFilter(elt, val));
                    }
                }
                // Add or
                if (disjunctiveRefinements.containsKey(elt.getKey())) {
                    facetFilters.put(orFilters);
                }
            }
            String[] facets = new String[]{disjunctiveFacet};
            //noinspection deprecation Deprecated for end-users
            queries.add(new Query(query).setHitsPerPage(0).setAnalytics(false)
                    .setAttributesToRetrieve().setAttributesToHighlight().setAttributesToSnippet()
                    .setFacets(facets).setFacetFilters(facetFilters));
        }
        return queries;
    }
static private @NonNull <T extends Collection<String>> List<Query> computeDisjunctiveFacetingQueries(@NonNull Query query, @NonNull Collection<String> disjunctiveFacets, @NonNull Map<String, T> refinements) {
        // Retain only refinements corresponding to the disjunctive facets.
        Map<String, ? extends Collection<String>> disjunctiveRefinements = filterDisjunctiveRefinements(disjunctiveFacets, refinements);

        // build queries
        List<Query> queries = new ArrayList<>();

        // first query: hits + regular facets
        JSONArray facetFilters = new JSONArray();
        for (Map.Entry<String, T> elt : refinements.entrySet()) {
            JSONArray orFilters = new JSONArray();

            for (String val : elt.getValue()) {
                // When already refined facet, or with existing refinements
                if (disjunctiveRefinements.containsKey(elt.getKey())) {
                    orFilters.put(formatFilter(elt, val));
                } else {
                    facetFilters.put(formatFilter(elt, val));
                }
            }
            // Add or
            if (disjunctiveRefinements.containsKey(elt.getKey())) {
                facetFilters.put(orFilters);
            }
        }

        //noinspection deprecation Deprecated for end-users
        queries.add(new Query(query).setFacetFilters(facetFilters));
        // one query per disjunctive facet (use all refinements but the current one + hitsPerPage=1 + single facet
        for (String disjunctiveFacet : disjunctiveFacets) {
            facetFilters = new JSONArray();
            for (Map.Entry<String, T> elt : refinements.entrySet()) {
                if (disjunctiveFacet.equals(elt.getKey())) {
                    continue;
                }
                JSONArray orFilters = new JSONArray();
                for (String val : elt.getValue()) {
                    if (disjunctiveRefinements.containsKey(elt.getKey())) {
                        orFilters.put(formatFilter(elt, val));
                    } else {
                        facetFilters.put(formatFilter(elt, val));
                    }
                }
                // Add or
                if (disjunctiveRefinements.containsKey(elt.getKey())) {
                    facetFilters.put(orFilters);
                }
            }
            String[] facets = new String[]{disjunctiveFacet};
            //noinspection deprecation Deprecated for end-users
            queries.add(new Query(query).setHitsPerPage(0).setAnalytics(false)
                    .setAttributesToRetrieve().setAttributesToHighlight().setAttributesToSnippet()
                    .setFacets(facets).setFacetFilters(facetFilters));
        }
        return queries;
    }
Compute the queries to run to implement disjunctive faceting.

@param query             The query.
@param disjunctiveFacets List of disjunctive facets.
@param refinements       The current refinements, mapping facet names to a list of values.
@return A list of queries suitable for {@link Index#multipleQueries}.