@@ -109,6 +109,10 @@ public function query($indexName, $q, $params)
109
109
{
110
110
$ this ->checkClient (__FUNCTION__ );
111
111
112
+ if (isset ($ params ['disjunctiveFacets ' ])) {
113
+ return $ this ->searchWithDisjunctiveFaceting ($ indexName , $ q , $ params );
114
+ }
115
+
112
116
return $ this ->client ->initIndex ($ indexName )->search ($ q , $ params );
113
117
}
114
118
@@ -491,7 +495,7 @@ private function prepareRecords(&$objects, $indexName)
491
495
492
496
if ($ object === false ) {
493
497
$ longestAttribute = $ this ->getLongestAttribute ($ previousObject );
494
- $ modifiedIds [] = $ indexName . '
498
+ $ modifiedIds [] = $ indexName . '
495
499
- ID ' . $ previousObject ['objectID ' ] . ' - skipped - longest attribute: ' . $ longestAttribute ;
496
500
497
501
unset($ objects [$ key ]);
@@ -506,10 +510,10 @@ private function prepareRecords(&$objects, $indexName)
506
510
if ($ modifiedIds && $ modifiedIds !== []) {
507
511
$ separator = php_sapi_name () === 'cli ' ? "\n" : '<br> ' ;
508
512
509
- $ errorMessage = 'Algolia reindexing:
510
- You have some records which are too big to be indexed in Algolia.
511
- They have either been truncated
512
- (removed attributes: ' . implode (', ' , $ this ->potentiallyLongAttributes ) . ')
513
+ $ errorMessage = 'Algolia reindexing:
514
+ You have some records which are too big to be indexed in Algolia.
515
+ They have either been truncated
516
+ (removed attributes: ' . implode (', ' , $ this ->potentiallyLongAttributes ) . ')
513
517
or skipped completely: ' . $ separator . implode ($ separator , $ modifiedIds );
514
518
515
519
if (php_sapi_name () === 'cli ' ) {
@@ -665,4 +669,123 @@ private function calculateObjectSize($object)
665
669
{
666
670
return mb_strlen (json_encode ($ object ));
667
671
}
672
+
673
+ protected function searchWithDisjunctiveFaceting ($ indexName , $ q , $ params )
674
+ {
675
+ if (! is_array ($ params ['disjunctiveFacets ' ]) || count ($ params ['disjunctiveFacets ' ]) <= 0 ) {
676
+ throw new \InvalidArgumentException ('disjunctiveFacets needs to be an non empty array ' );
677
+ }
678
+
679
+ if (isset ($ params ['filters ' ])) {
680
+ throw new \InvalidArgumentException ('You can not use disjunctive faceting and the filters parameter ' );
681
+ }
682
+
683
+ /**
684
+ * Prepare queries
685
+ */
686
+ // Get the list of disjunctive queries to do: 1 per disjunctive facet
687
+ $ disjunctiveQueries = $ this ->getDisjunctiveQueries ($ params );
688
+
689
+ // Format disjunctive queries for multipleQueries call
690
+ foreach ($ disjunctiveQueries as &$ disjunctiveQuery ) {
691
+ $ disjunctiveQuery ['indexName ' ] = $ indexName ;
692
+ $ disjunctiveQuery ['query ' ] = $ q ;
693
+ unset($ disjunctiveQuery ['disjunctiveFacets ' ]);
694
+ }
695
+
696
+ // Merge facets and disjunctiveFacets for the hits query
697
+ $ facets = isset ($ params ['facets ' ]) ? $ params ['facets ' ] : [];
698
+ $ facets = array_merge ($ facets , $ params ['disjunctiveFacets ' ]);
699
+ unset($ params ['disjunctiveFacets ' ]);
700
+
701
+ // format the hits query for multipleQueries call
702
+ $ params ['query ' ] = $ q ;
703
+ $ params ['indexName ' ] = $ indexName ;
704
+ $ params ['facets ' ] = $ facets ;
705
+
706
+ // Put the hit query first
707
+ array_unshift ($ disjunctiveQueries , $ params );
708
+
709
+ /**
710
+ * Do all queries in one call
711
+ */
712
+ $ results = $ this ->client ->multipleQueries (array_values ($ disjunctiveQueries ));
713
+ $ results = $ results ['results ' ];
714
+
715
+ /**
716
+ * Merge facets from disjunctive queries with facets from the hits query
717
+ */
718
+ // The first query is the hits query that the one we'll return to the user
719
+ $ queryResults = array_shift ($ results );
720
+
721
+ // To be able to add facets from disjunctive query we create 'facets' key in case we only have disjunctive facets
722
+ if (false === isset ($ queryResults ['facets ' ])) {
723
+ $ queryResults ['facets ' ] =[];
724
+ }
725
+
726
+ foreach ($ results as $ disjunctiveResults ) {
727
+ if (isset ($ disjunctiveResults ['facets ' ])) {
728
+ foreach ($ disjunctiveResults ['facets ' ] as $ facetName => $ facetValues ) {
729
+ $ queryResults ['facets ' ][$ facetName ] = $ facetValues ;
730
+ }
731
+ }
732
+ }
733
+
734
+ return $ queryResults ;
735
+ }
736
+
737
+ protected function getDisjunctiveQueries ($ queryParams )
738
+ {
739
+ $ queriesParams = [];
740
+
741
+ foreach ($ queryParams ['disjunctiveFacets ' ] as $ facetName ) {
742
+ $ params = $ queryParams ;
743
+ $ params ['facets ' ] = [$ facetName ];
744
+ $ facetFilters = isset ($ params ['facetFilters ' ]) ? $ params ['facetFilters ' ] : [];
745
+ $ numericFilters = isset ($ params ['numericFilters ' ]) ? $ params ['numericFilters ' ] : [];
746
+
747
+ $ additionalParams = [
748
+ 'hitsPerPage ' => 1 ,
749
+ 'page ' => 0 ,
750
+ 'attributesToRetrieve ' => [],
751
+ 'attributesToHighlight ' => [],
752
+ 'attributesToSnippet ' => [],
753
+ 'analytics ' => false ,
754
+ ];
755
+
756
+ $ additionalParams ['facetFilters ' ] =
757
+ $ this ->getAlgoliaFiltersArrayWithoutCurrentRefinement ($ facetFilters , $ facetName . ': ' );
758
+ $ additionalParams ['numericFilters ' ] =
759
+ $ this ->getAlgoliaFiltersArrayWithoutCurrentRefinement ($ numericFilters , $ facetName );
760
+
761
+ $ queriesParams [$ facetName ] = array_merge ($ params , $ additionalParams );
762
+ }
763
+
764
+ return $ queriesParams ;
765
+ }
766
+
767
+ protected function getAlgoliaFiltersArrayWithoutCurrentRefinement ($ filters , $ needle )
768
+ {
769
+ // iterate on each filters which can be string or array and filter out every refinement matching the needle
770
+ for ($ i = 0 ; $ i < count ($ filters ); $ i ++) {
771
+ if (is_array ($ filters [$ i ])) {
772
+ foreach ($ filters [$ i ] as $ filter ) {
773
+ if (mb_substr ($ filter , 0 , mb_strlen ($ needle )) === $ needle ) {
774
+ unset($ filters [$ i ]);
775
+ $ filters = array_values ($ filters );
776
+ $ i --;
777
+ break ;
778
+ }
779
+ }
780
+ } else {
781
+ if (mb_substr ($ filters [$ i ], 0 , mb_strlen ($ needle )) === $ needle ) {
782
+ unset($ filters [$ i ]);
783
+ $ filters = array_values ($ filters );
784
+ $ i --;
785
+ }
786
+ }
787
+ }
788
+
789
+ return $ filters ;
790
+ }
668
791
}
0 commit comments