@@ -5,36 +5,115 @@ namespace Nest
55{
66 internal static class BoolFilterExtensions
77 {
8- internal static bool CanMergeMustAndMustNots ( this IBoolFilter bq )
8+ internal static bool IsBoolFilterWithOnlyMustNots ( this IFilterContainer container )
99 {
10- return bq == null || ! ( ( IBoolFilter ) bq ) . Should . HasAny ( ) ;
10+ return container != null && container . Bool != null
11+ && ! container . Bool . Must . HasAny ( )
12+ && ! container . Bool . Should . HasAny ( )
13+ && container . Bool . MustNot . HasAny ( ) ;
1114 }
1215
13- internal static bool CanJoinShould ( this IBoolFilter bq )
16+ internal static bool CanMergeMustAndMustNots ( this IFilterContainer container )
1417 {
15- var bf = ( IBoolFilter ) bq ;
16- return bq == null
17- || (
18- ( bf . Should . HasAny ( ) && ! bf . Must . HasAny ( ) && ! bf . MustNot . HasAny ( ) )
19- || ! bf . Should . HasAny ( )
20- ) ;
18+ return ! container . IsStrict && container . Bool . CanMergeMustAndMustNots ( ) ;
2119 }
22-
23- internal static IEnumerable < IFilterContainer > MergeShouldFilters ( this IFilterContainer lbq , IFilterContainer rbq )
20+
21+ internal static bool CanMergeMustAndMustNots ( this IBoolFilter boolFilter )
22+ {
23+ return boolFilter == null || ! boolFilter . Should . HasAny ( ) ;
24+
25+ }
26+
27+ internal static bool CanMergeShould ( this IFilterContainer container )
28+ {
29+ return ! container . IsStrict && container . Bool . CanMergeShould ( ) ;
30+ }
31+
32+ internal static bool CanMergeShould ( this IBoolFilter boolFilter )
33+ {
34+ return boolFilter == null
35+ || (
36+ ( boolFilter . Should . HasAny ( ) && ! boolFilter . Must . HasAny ( ) && ! boolFilter . MustNot . HasAny ( ) )
37+ || ! boolFilter . Should . HasAny ( )
38+ ) ;
39+ }
40+
41+ internal static FilterContainer MergeMustFilters ( this IFilterContainer leftContainer , IFilterContainer rightContainer )
42+ {
43+ if ( ! leftContainer . CanMergeMustAndMustNots ( ) || ! rightContainer . CanMergeMustAndMustNots ( ) )
44+ {
45+ if ( rightContainer . IsBoolFilterWithOnlyMustNots ( ) )
46+ return CreateMustContainer ( new [ ] { leftContainer } , rightContainer . Bool . MustNot ) ;
47+ if ( leftContainer . IsBoolFilterWithOnlyMustNots ( ) )
48+ return CreateMustContainer ( new [ ] { rightContainer } , leftContainer . Bool . MustNot ) ;
49+ return CreateMustContainer ( new [ ] { leftContainer , rightContainer } , null ) ;
50+ }
51+
52+ var mustNots = OrphanMustNots ( leftContainer )
53+ . EagerConcat ( OrphanMustNots ( rightContainer ) ) ;
54+
55+ var leftClauses = CreateMustClauses ( leftContainer ) ;
56+ var rightClauses = CreateMustClauses ( rightContainer ) ;
57+
58+ var mustClauses = leftClauses . EagerConcat ( rightClauses ) ;
59+ var container = CreateMustContainer ( mustClauses , mustNots ) ;
60+ return container ;
61+ }
62+
63+ private static IEnumerable < IFilterContainer > CreateMustClauses ( IFilterContainer container )
64+ {
65+ var boolFilter = container . Bool ;
66+ var hasMustClauses = boolFilter != null && boolFilter . Must . HasAny ( ) ;
67+ if ( hasMustClauses ) return boolFilter . Must ;
68+ if ( boolFilter != null && boolFilter . IsConditionless )
69+ return Enumerable . Empty < IFilterContainer > ( ) ;
70+
71+ return new [ ] { container } ;
72+ }
73+
74+ private static IEnumerable < IFilterContainer > OrphanMustNots ( IFilterContainer container )
75+ {
76+ var lBoolFilter = container . Bool ;
77+ if ( lBoolFilter == null || ! lBoolFilter . MustNot . HasAny ( ) ) return null ;
78+
79+ var mustNotFilters = lBoolFilter . MustNot . ToList ( ) ;
80+ lBoolFilter . MustNot = null ;
81+ return mustNotFilters ;
82+ }
83+
84+ internal static FilterContainer MergeShouldFilters ( this IFilterContainer leftContainer , IFilterContainer rightContainer )
2485 {
25- var lBoolDescriptor = lbq . Bool ;
26- var lHasShouldFilters = lBoolDescriptor != null &&
27- ( ( IBoolFilter ) lBoolDescriptor ) . Should . HasAny ( ) ;
86+ if ( ! leftContainer . CanMergeShould ( ) || ! leftContainer . CanMergeShould ( ) )
87+ return CreateShouldContainer ( new List < IFilterContainer > { leftContainer , rightContainer } ) ;
88+
89+ var lBoolFilter = leftContainer . Bool ;
90+ var rBoolFilter = rightContainer . Bool ;
2891
29- var rBoolDescriptor = rbq . Bool ;
30- var rHasShouldFilters = rBoolDescriptor != null &&
31- ( ( IBoolFilter ) rBoolDescriptor ) . Should . HasAny ( ) ;
92+ var lHasShouldFilters = lBoolFilter != null && lBoolFilter . Should . HasAny ( ) ;
93+ var rHasShouldFilters = rBoolFilter != null && rBoolFilter . Should . HasAny ( ) ;
3294
95+ var lq = lHasShouldFilters ? lBoolFilter . Should : new [ ] { leftContainer } ;
96+ var rq = rHasShouldFilters ? rBoolFilter . Should : new [ ] { rightContainer } ;
3397
34- var lq = lHasShouldFilters ? ( ( IBoolFilter ) lBoolDescriptor ) . Should : new [ ] { lbq } ;
35- var rq = rHasShouldFilters ? ( ( IBoolFilter ) rBoolDescriptor ) . Should : new [ ] { rbq } ;
98+ var shouldClauses = lq . EagerConcat ( rq ) ;
99+ return CreateShouldContainer ( shouldClauses ) ;
100+ }
36101
37- return lq . Concat ( rq ) ;
102+ internal static FilterContainer CreateShouldContainer ( IList < IFilterContainer > shouldClauses )
103+ {
104+ IFilterContainer q = new FilterContainer ( ) ;
105+ q . Bool = new BoolBaseFilterDescriptor ( ) ;
106+ q . Bool . Should = shouldClauses . NullIfEmpty ( ) ;
107+ return q as FilterContainer ;
108+ }
109+
110+ internal static FilterContainer CreateMustContainer ( IList < IFilterContainer > mustClauses , IEnumerable < IFilterContainer > mustNotClauses )
111+ {
112+ IFilterContainer q = new FilterContainer ( ) ;
113+ q . Bool = new BoolBaseFilterDescriptor ( ) ;
114+ q . Bool . Must = mustClauses . NullIfEmpty ( ) ;
115+ q . Bool . MustNot = mustNotClauses . NullIfEmpty ( ) ;
116+ return q as FilterContainer ;
38117 }
39118 }
40119}
0 commit comments