Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Star Tree] [Search] Support for metric aggregations with/without term query #15289

Open
wants to merge 18 commits into
base: main
Choose a base branch
from

Conversation

sandeshkr419
Copy link
Contributor

@sandeshkr419 sandeshkr419 commented Aug 19, 2024

Disclaimer

These changes are built on top of unmerged/in-review indexing changes, Reviewers kindly ignore this commit while reviewing this change. When the depending changes are merged, will remove the Do not merge from title, and add chngelog to the PR - avoiding adding now to avoid unnecessary rebasing/conflicts.

Description

For an index supporting star-tree composite index, this changes tries to achieve resolving a metric aggregation with/without a numeric terms query with the help of star-tree.

In present state, the PR capture changes for sum, max, min, avg, value-count aggregation. Once the high level changes in sum aggregation are reviewed, will increment with other aggregations.

Approach

A new StarTreeQuery is introduced which helps resolve to star-tree documents. This star-tree query is formed (if it can be) at the shard level, this is not done at coordinator level to avoid node to node transportation. Also, all the information is present at shard level and OpenSearch does majority of query rewrite at shard level itself. This star tree query is encapsulated in an OriginalOrStarTreeQuery which helps preserve the original query alongwith the new star tree query. This encapsulation is done so as to preserve both the queries and decision whether to use which query can be taken at a segment level.

High Level Operations (to make code reviewing simple):

  1. Parsing a Search Query, to decide whether or not to use star tree flow: SearchService.java, QueryShardContext.java
  2. Parsed SearchQuery: StarTreeQuery.java, OriginalOrStarTreeQuery.java
  3. Utilities for resolving star-tree given certain predicates (derived from term query of search request), and tree traversal - StarTreeFilter.java
  4. Changes in 5 metric Aggregators - SumAggregator.java, MaxAggregator.java, MinAggregator.java, AvgAggregator.java, ValueCountAggregator.java
  5. Supporting changes - changes in access level of aggregator factory classes so identify correct aggregations during request parsing.

TODO in this PR:

  1. Test cases to be added.
  2. Support for max, min, count, avg metric aggregations.

This PR depends on #14809, therefore the depending unmerged changes have been utilized for now in my private fork to discuss the changes in parallel.

Example query shape:

No query + Agg:

{
    "size": 0,
    "aggs": {
                        "sum_status": {
                            "sum": {
                                "field": "size"
                            }
                        }
                    }
}

Original Response:

{
    "took": 8378,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1009,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "sum_status": {
            "value": 615579.0
        }
    }
}

Star Tree Response:

{
    "took": 16394,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "sum_status": {
            "value": 615579.0
        }
    }
}

Request:

{
    "query": {
        "term": {
            "status": 200
        }
    },
    "size": 0,
    "aggs": {
                        "sum_status": {
                            "sum": {
                                "field": "size"
                            }
                        }
                    }
}

Original Response:

{
    "took": 4038,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 42,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "sum_status": {
            "value": 24745.0
        }
    }
}

Star Tree Flow Response:

{
    "took": 21120,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "sum_status": {
            "value": 24745.0
        }
    }
}

Multi-aggs in a single request:

{ 
    "query": {
        "term": {
            "status": 201
        }
    },
    "size": 0,
    "aggs": {
                        "sum_status": {
                            "sum": {
                                "field": "size"
                            }
                        },
                        "max_status": {
                            "max": {
                                "field": "size"
                            }
                        },
                        "min_status": {
                            "min": {
                                "field": "size"
                            }
                        },
                        "avg_status": {
                            "avg": {
                                "field": "size"
                            }
                        },
                        "count_status": {
                            "value_count": {
                                "field": "size"
                            }
                        }

                    }
}

Star Tree Response:

{
    "took": 28,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 3,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "max_status": {
            "value": 1000.0
        },
        "sum_status": {
            "value": 32154.0
        },
        "count_status": {
            "value": 53
        },
        "avg_status": {
            "value": 606.6792452830189
        },
        "min_status": {
            "value": 200.0
        }
    }
}

Unsupported Metric Operation via star-tree:

{ 
    "query": {
        "term": {
            "status": 201
        }
    },
    "size": 0,
    "aggs": {
                        "sum_status": {
                            "sum": {
                                "field": "size"
                            }
                        },
                        "max_status": {
                            "max": {
                                "field": "size"
                            }
                        },
                        "min_status": {
                            "min": {
                                "field": "size"
                            }
                        },
                        "avg_status": {
                            "avg": {
                                "field": "size"
                            }
                        },
                        "count_status": {
                            "stats": {
                                "field": "size"
                            }
                        }

                    }
}

Defaults to original code-flow (verified by hits reported):

{
    "took": 137433,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 53,
            "relation": "eq"
        },
        "max_score": null,
        "hits": []
    },
    "aggregations": {
        "max_status": {
            "value": 1000.0
        },
        "sum_status": {
            "value": 32154.0
        },
        "count_status": {
            "count": 53,
            "min": 200.0,
            "max": 1000.0,
            "avg": 606.6792452830189,
            "sum": 32154.0
        },
        "avg_status": {
            "value": 606.6792452830189
        },
        "min_status": {
            "value": 200.0
        }
    }
}

Approach:

  1. The query shape is identified at the shard level (SearchService.java) and the query/aggregation (if can be resolved by star-tree) is parsed to a star-tree query.
  2. The star-tree query is wrapped around OriginalOrStarTreeQuery to preserve the original query - this is because the decision to decide which implementation (default/startree) to use can be taken for a segment level.
  3. If star-tree can be utilized to answer the query, the star-tree document set is then collected by the relevant aggregator/collector. In this POC, I have made changes to SumAggregator to demonstrate the flow of changes.

Related Issues

#15257

Check List

  • New functionality includes testing.
    • All tests pass
  • New functionality has been documented.
    • New functionality has javadoc added
  • Failing checks are inspected and point to the corresponding known issue(s) (See: Troubleshooting Failing Builds)
  • Commits are signed per the DCO using --signoff
  • Commit changes are listed out in CHANGELOG.md file (See: Changelog)
  • Public documentation issue/PR created

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.

@sandeshkr419 sandeshkr419 changed the title St0 Star Tree Request/Response structure Aug 19, 2024
Copy link
Contributor

❌ Gradle check result for ad54ace: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

Copy link
Contributor

❌ Gradle check result for 6c6be02: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

Copy link
Contributor

❌ Gradle check result for 995db38: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

Copy link
Contributor

❌ Gradle check result for 885a383: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

Copy link
Contributor

❌ Gradle check result for 9491aae: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

Copy link
Contributor

❌ Gradle check result for a01c6e2: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?


@Override
public String toString(String field) {
return null;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit : lets fix this to contain actual info

An example :

@Override
    public String toString(String field) {
        return "BinaryDocValuesRangeQuery(fieldName=" + field + ",from=" + originalFrom + ",to=" + originalTo + ")";
    }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is used to Prints a user-readable version of this query. - since this is not exposed to user and is utilized internally, I'm planning to return null here, and for OriginalOrStarTreeQuery class - I am thinking of printing the originalQuery::toString. How does this sounds?

Copy link
Contributor

❌ Gradle check result for e4a270a: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

Signed-off-by: Sandesh Kumar <[email protected]>
Signed-off-by: Sandesh Kumar <[email protected]>
Signed-off-by: Sandesh Kumar <[email protected]>
Signed-off-by: Sandesh Kumar <[email protected]>
Signed-off-by: Sandesh Kumar <[email protected]>
Signed-off-by: Sandesh Kumar <[email protected]>
Signed-off-by: Sandesh Kumar <[email protected]>
Signed-off-by: Sandesh Kumar <[email protected]>
Signed-off-by: Sandesh Kumar <[email protected]>
Signed-off-by: Sandesh Kumar <[email protected]>
Signed-off-by: Sandesh Kumar <[email protected]>
Signed-off-by: Sandesh Kumar <[email protected]>
Copy link
Contributor

github-actions bot commented Sep 5, 2024

❕ Gradle check result for 4637ee4: UNSTABLE

Please review all flaky tests that succeeded after retry and create an issue if one does not already exist to track the flaky failure.

Copy link

codecov bot commented Sep 5, 2024

Codecov Report

Attention: Patch coverage is 69.44444% with 110 lines in your changes missing coverage. Please review.

Project coverage is 71.86%. Comparing base (729e40d) to head (4637ee4).
Report is 45 commits behind head on main.

Files with missing lines Patch % Lines
...org/opensearch/search/startree/StarTreeFilter.java 62.26% 34 Missing and 6 partials ⚠️
...x/datacube/startree/utils/StarTreeQueryHelper.java 61.90% 8 Missing and 16 partials ⚠️
.../org/opensearch/search/startree/StarTreeQuery.java 50.00% 14 Missing and 2 partials ⚠️
...earch/search/startree/OriginalOrStarTreeQuery.java 41.66% 6 Missing and 1 partial ⚠️
...rch/search/aggregations/metrics/MaxAggregator.java 79.16% 3 Missing and 2 partials ⚠️
...rch/search/aggregations/metrics/MinAggregator.java 79.16% 3 Missing and 2 partials ⚠️
...main/java/org/opensearch/search/SearchService.java 75.00% 1 Missing and 2 partials ⚠️
...rch/search/aggregations/metrics/AvgAggregator.java 93.93% 0 Missing and 2 partials ⚠️
...rch/search/aggregations/metrics/SumAggregator.java 92.59% 0 Missing and 2 partials ⚠️
...rch/aggregations/metrics/ValueCountAggregator.java 87.50% 0 Missing and 2 partials ⚠️
... and 4 more
Additional details and impacted files
@@             Coverage Diff              @@
##               main   #15289      +/-   ##
============================================
- Coverage     71.95%   71.86%   -0.10%     
- Complexity    64192    64241      +49     
============================================
  Files          5270     5276       +6     
  Lines        300052   300526     +474     
  Branches      43368    43445      +77     
============================================
+ Hits         215917   215983      +66     
- Misses        66442    66829     +387     
- Partials      17693    17714      +21     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
v2.18.0 Issues and PRs related to version 2.18.0
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

6 participants