/// <summary> /// Handles cases where either side is a bool which indicates it can't be merged yet the other side is mergable. /// A side is considered unmergable if its locked (has important metadata) or has should clauses. /// Instead of always wrapping these cases in another bool we merge to unmergable side into to others must clause therefor flattening the generated graph /// </summary> private static bool TryHandleUnmergableBools( QueryContainer leftContainer, QueryContainer rightContainer, IBoolQuery leftBool, IBoolQuery rightBool, out QueryContainer c) { c = null; var leftCantMergeAnd = leftBool != null && !leftBool.CanMergeAnd(); var rightCantMergeAnd = rightBool != null && !rightBool.CanMergeAnd(); if (!leftCantMergeAnd && !rightCantMergeAnd) return false; if (leftCantMergeAnd && rightCantMergeAnd) c = CreateMustContainer(leftContainer, rightContainer); //right can't merge but left can and is a bool so we add left to the must clause of right else if (!leftCantMergeAnd && leftBool != null && rightCantMergeAnd) { leftBool.Must = leftBool.Must.AddIfNotNull(rightContainer); c = leftContainer; } //right can't merge and left is not a bool, we forcefully create a wrapped must container else if (!leftCantMergeAnd && leftBool == null && rightCantMergeAnd) c = CreateMustContainer(leftContainer, rightContainer); //left can't merge but right can and is a bool so we add left to the must clause of right else if (leftCantMergeAnd && !rightCantMergeAnd && rightBool != null) { rightBool.Must = rightBool.Must.AddIfNotNull(leftContainer); c = rightContainer; } //left can't merge and right is not a bool, we forcefully create a wrapped must container else if (leftCantMergeAnd && !rightCantMergeAnd && rightBool == null) c = CreateMustContainer(new Containers { leftContainer, rightContainer }, null); return c != null; }
private static bool TryFlattenShould( QueryContainer leftContainer, QueryContainer rightContainer, IBoolQuery leftBool, IBoolQuery rightBool, out QueryContainer c) { c = null; var leftCanMerge = leftContainer.CanMergeShould(); var rightCanMerge = rightContainer.CanMergeShould(); if (!leftCanMerge && !rightCanMerge) c = CreateShouldContainer(new Containers { leftContainer, rightContainer }); //left can merge but right's bool can not instead of wrapping into a new bool we inject the whole bool into left else if (leftCanMerge && !rightCanMerge && rightBool != null) { leftBool.Should = leftBool.Should.AddIfNotNull(rightContainer); c = leftContainer; } else if (rightCanMerge && !leftCanMerge && leftBool != null) { rightBool.Should = rightBool.Should.AddIfNotNull(leftContainer); c = rightContainer; } return c != null; }
/// <summary> /// Both Sides are bools, but one of them has only should clauses so we should wrap into a new container. /// Unless we know one of the sides is a bool with only a must who's clauses are all bools with only shoulds. /// This is a piece of metadata we set at the bools creation time so we do not have to itterate the clauses on each combination /// In this case we can optimize the generated graph by merging and preventing stack overflows /// </summary> private static bool TryHandleBoolsWithOnlyShouldClauses( QueryContainer leftContainer, QueryContainer rightContainer, IBoolQuery leftBool, IBoolQuery rightBool, out QueryContainer c) { c = null; var leftHasOnlyShoulds = leftBool.HasOnlyShouldClauses(); var rightHasOnlyShoulds = rightBool.HasOnlyShouldClauses(); if (!leftHasOnlyShoulds && !rightHasOnlyShoulds) return false; if (leftContainer.HoldsOnlyShouldMusts && rightHasOnlyShoulds) { leftBool.Must = leftBool.Must.AddIfNotNull(rightContainer); c = leftContainer; } else if (rightContainer.HoldsOnlyShouldMusts && leftHasOnlyShoulds) { rightBool.Must = rightBool.Must.AddIfNotNull(leftContainer); c = rightContainer; } else { c = CreateMustContainer(new Containers { leftContainer, rightContainer }, null); c.HoldsOnlyShouldMusts = rightHasOnlyShoulds && leftHasOnlyShoulds; } return true; }
private static bool CanMergeShould(this IBoolQuery boolQuery) => boolQuery == null || (!boolQuery.Locked && boolQuery.HasOnlyShouldClauses());
public virtual void Visit(IBoolQuery query) { }
internal static bool IsConditionless(IBoolQuery q) => q.Must.NotWritable() && q.MustNot.NotWritable() && q.Should.NotWritable() && q.Filter.NotWritable();
internal static bool HasOnlyFilterClauses(this IBoolQuery boolQuery) => boolQuery != null && !boolQuery.IsVerbatim && !boolQuery.Locked && !boolQuery.Should.HasAny() && !boolQuery.Must.HasAny() && !boolQuery.MustNot.HasAny() && boolQuery.Filter.HasAny();
private static bool CanMergeShould(this IBoolQuery boolQuery) => boolQuery != null && boolQuery.IsWritable && !boolQuery.Locked && boolQuery.HasOnlyShouldClauses();
private static bool CanMergeAnd(this IBoolQuery boolQuery) => boolQuery != null && !boolQuery.Locked && !boolQuery.Should.HasAny();
private static bool CanMergeAnd(this IBoolQuery boolQuery) => //boolQuery != null && boolQuery.IsWritable && !boolQuery.Locked && !boolQuery.Should.HasAny(); boolQuery != null && !boolQuery.Locked && !boolQuery.Should.HasAny();
internal static bool CanMergeMustAndMustNots(this IBoolQuery bq) { return(bq == null || !bq.Should.HasAny()); }
public virtual void Visit(IBoolQuery baseQuery) { }
private static bool CanMergeShould(this IBoolQuery boolQuery) => boolQuery == null || (!boolQuery.Locked && (boolQuery.HasOnlyShouldClauses() || boolQuery.HasOnlyMustNotClauses() || boolQuery.HasOnlyFilterClauses()) );
internal static bool Locked(IBoolQuery q) => !q.Name.IsNullOrEmpty() || q.Boost.HasValue || q.DisableCoord.HasValue || q.MinimumShouldMatch != null;
private static bool TryFlattenShould( QueryContainer leftContainer, QueryContainer rightContainer, IBoolQuery leftBool, IBoolQuery rightBool, out QueryContainer c ) { c = null; var leftCanMerge = leftContainer.CanMergeShould(); var rightCanMerge = rightContainer.CanMergeShould(); if (!leftCanMerge && !rightCanMerge) { c = CreateShouldContainer(new Containers { leftContainer, rightContainer }); } //left can merge but right's bool can not instead of wrapping into a new bool we inject the whole bool into left else if (leftCanMerge && !rightCanMerge && rightBool != null) { leftBool.Should = leftBool.Should.AddIfNotNull(rightContainer); c = leftContainer; } else if (rightCanMerge && !leftCanMerge && leftBool != null) { rightBool.Should = rightBool.Should.AddIfNotNull(leftContainer); c = rightContainer; } return(c != null); }
/// <summary> /// Handles cases where either side is a bool which indicates it can't be merged yet the other side is mergable. /// A side is considered unmergable if its locked (has important metadata) or has should clauses. /// Instead of always wrapping these cases in another bool we merge to unmergable side into to others must clause therefor flattening the /// generated graph /// </summary> private static bool TryHandleUnmergableBools( QueryContainer leftContainer, QueryContainer rightContainer, IBoolQuery leftBool, IBoolQuery rightBool, out QueryContainer c ) { c = null; var leftCantMergeAnd = leftBool != null && !leftBool.CanMergeAnd(); var rightCantMergeAnd = rightBool != null && !rightBool.CanMergeAnd(); if (!leftCantMergeAnd && !rightCantMergeAnd) { return(false); } if (leftCantMergeAnd && rightCantMergeAnd) { c = CreateMustContainer(leftContainer, rightContainer); } //right can't merge but left can and is a bool so we add left to the must clause of right else if (!leftCantMergeAnd && leftBool != null && rightCantMergeAnd) { leftBool.Must = leftBool.Must.AddIfNotNull(rightContainer); c = leftContainer; } //right can't merge and left is not a bool, we forcefully create a wrapped must container else if (!leftCantMergeAnd && leftBool == null && rightCantMergeAnd) { c = CreateMustContainer(leftContainer, rightContainer); } //left can't merge but right can and is a bool so we add left to the must clause of right else if (leftCantMergeAnd && !rightCantMergeAnd && rightBool != null) { rightBool.Must = rightBool.Must.AddIfNotNull(leftContainer); c = rightContainer; } //left can't merge and right is not a bool, we forcefully create a wrapped must container else if (leftCantMergeAnd && !rightCantMergeAnd && rightBool == null) { c = CreateMustContainer(new Containers { leftContainer, rightContainer }, null); } return(c != null); }
public virtual void Visit(IBoolQuery query) { Write("bool"); }
/// <summary> /// Both Sides are bools, but one of them has only should clauses so we should wrap into a new container. /// Unless we know one of the sides is a bool with only a must who's clauses are all bools with only shoulds. /// This is a piece of metadata we set at the bools creation time so we do not have to itterate the clauses on each combination /// In this case we can optimize the generated graph by merging and preventing stack overflows /// </summary> private static bool TryHandleBoolsWithOnlyShouldClauses( QueryContainer leftContainer, QueryContainer rightContainer, IBoolQuery leftBool, IBoolQuery rightBool, out QueryContainer c ) { c = null; var leftHasOnlyShoulds = leftBool.HasOnlyShouldClauses(); var rightHasOnlyShoulds = rightBool.HasOnlyShouldClauses(); if (!leftHasOnlyShoulds && !rightHasOnlyShoulds) { return(false); } if (leftContainer.HoldsOnlyShouldMusts && rightHasOnlyShoulds) { leftBool.Must = leftBool.Must.AddIfNotNull(rightContainer); c = leftContainer; } else if (rightContainer.HoldsOnlyShouldMusts && leftHasOnlyShoulds) { rightBool.Must = rightBool.Must.AddIfNotNull(leftContainer); c = rightContainer; } else { c = CreateMustContainer(new Containers { leftContainer, rightContainer }, null); c.HoldsOnlyShouldMusts = rightHasOnlyShoulds && leftHasOnlyShoulds; } return(true); }