Skip to content

Commit 4cfc3fe

Browse files
committed
refactored bitwise boolean merging code to be actually readable
1 parent 6feceda commit 4cfc3fe

File tree

13 files changed

+332
-422
lines changed

13 files changed

+332
-422
lines changed

src/Nest/DSL/Filter/BoolFilterExtensions.cs

Lines changed: 99 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)