-
Notifications
You must be signed in to change notification settings - Fork 177
Mvexpand feature #4675
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
base: main
Are you sure you want to change the base?
Mvexpand feature #4675
Changes from 11 commits
445799f
427af0f
83d7786
7f6e127
dcbf56b
a3c1384
148ccc5
f5a9e82
2cc60ad
18cbba4
60fa2ad
d248cb0
a28894a
825c52e
dc76a55
8319583
6d87133
b83ab21
c84703d
de82b65
6c6e0ec
069d52e
2f3aeb6
e584368
a41b081
bf018b7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| /* | ||
| * Copyright OpenSearch Contributors | ||
| * SPDX-License-Identifier: Apache-2.0 | ||
| */ | ||
|
|
||
| package org.opensearch.sql.ast.tree; | ||
|
|
||
| import com.google.common.collect.ImmutableList; | ||
| import java.util.List; | ||
| import javax.annotation.Nullable; | ||
| import lombok.EqualsAndHashCode; | ||
| import lombok.Getter; | ||
| import lombok.ToString; | ||
| import org.opensearch.sql.ast.AbstractNodeVisitor; | ||
| import org.opensearch.sql.ast.expression.Field; | ||
|
|
||
| /** AST node representing an {@code mvexpand <field> [limit N]} operation. */ | ||
| @ToString | ||
| @EqualsAndHashCode(callSuper = false) | ||
| public class MvExpand extends UnresolvedPlan { | ||
|
|
||
| private UnresolvedPlan child; | ||
| @Getter private final Field field; | ||
| @Getter @Nullable private final Integer limit; | ||
|
|
||
| public MvExpand(Field field, @Nullable Integer limit) { | ||
| this.field = field; | ||
| this.limit = limit; | ||
| } | ||
|
|
||
| @Override | ||
| public MvExpand attach(UnresolvedPlan child) { | ||
| this.child = child; | ||
| return this; | ||
| } | ||
|
|
||
| public Field getField() { | ||
| return field; | ||
| } | ||
|
|
||
| @Nullable | ||
| public Integer getLimit() { | ||
srikanthpadakanti marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return limit; | ||
| } | ||
srikanthpadakanti marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| @Override | ||
| public List<UnresolvedPlan> getChild() { | ||
| return this.child == null ? ImmutableList.of() : ImmutableList.of(this.child); | ||
| } | ||
|
|
||
| @Override | ||
| public <T, C> T accept(AbstractNodeVisitor<T, C> nodeVisitor, C context) { | ||
| return nodeVisitor.visitMvExpand(this, context); | ||
| } | ||
| } | ||
srikanthpadakanti marked this conversation as resolved.
Show resolved
Hide resolved
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,180 @@ | ||
| ============= | ||
| mvexpand | ||
| ============= | ||
|
|
||
| .. rubric:: Table of contents | ||
|
|
||
| .. contents:: | ||
| :local: | ||
| :depth: 2 | ||
|
|
||
|
|
||
| Description | ||
| ============ | ||
| | The ``mvexpand`` command expands each value in a multivalue (array) field into a separate row, similar to Splunk's `mvexpand` command. | ||
| | For each document, every value in the specified field is returned as a new row. This is especially useful for log analytics and data exploration involving array fields. | ||
|
|
||
| | Key features of ``mvexpand``: | ||
| - Expands array fields into multiple rows, one per value. | ||
| - Supports an optional ``limit`` parameter to restrict the number of expanded values per document. | ||
| - Handles empty, null, and non-array fields gracefully. | ||
| - Works as a streaming/distributable command for performance and scalability. | ||
|
|
||
| Version | ||
| ======= | ||
| 3.3.0 | ||
dai-chen marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| Syntax | ||
| ====== | ||
| mvexpand <field> [limit=<int>] | ||
|
|
||
| * **field**: The multivalue (array) field to expand. (Required) | ||
| * **limit**: Maximum number of values per document to expand. (Optional) | ||
dai-chen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| Usage | ||
| ===== | ||
| Basic expansion:: | ||
|
|
||
| os> source=logs | mvexpand tags | ||
|
|
||
| Expansion with limit:: | ||
|
|
||
| os> source=docs | mvexpand ids limit=3 | ||
|
|
||
| Limitations | ||
| =========== | ||
| - Only one field can be expanded per mvexpand command. | ||
| - For non-array fields, the value is returned as-is. | ||
| - For empty or null arrays, no rows are returned. | ||
| - Large arrays may be subject to resource/memory limits; exceeding them results in an error or warning. | ||
|
|
||
| Examples and Edge Cases | ||
| ======================= | ||
|
|
||
| Example 1: Basic Expansion | ||
| -------------------------- | ||
| Expand all values from an array field. | ||
|
|
||
| Input document:: | ||
|
|
||
| { "tags": ["error", "warning", "info"] } | ||
|
|
||
| PPL query:: | ||
|
|
||
| os> source=logs | mvexpand tags | ||
| fetched rows / total rows = 3/3 | ||
| +--------+ | ||
| | tags | | ||
| +--------+ | ||
| | error | | ||
| | warning| | ||
| | info | | ||
| +--------+ | ||
|
|
||
| Example 2: Expansion with Limit | ||
| ------------------------------- | ||
| Limit the number of expanded values per document. | ||
|
|
||
| Input document:: | ||
|
|
||
| { "ids": [1, 2, 3, 4, 5] } | ||
|
|
||
| PPL query:: | ||
|
|
||
| os> source=docs | mvexpand ids limit=3 | ||
| fetched rows / total rows = 3/3 | ||
| +-----+ | ||
| | ids | | ||
| +-----+ | ||
| | 1 | | ||
| | 2 | | ||
| | 3 | | ||
| +-----+ | ||
|
|
||
| Example 3: Empty or Null Arrays | ||
| ------------------------------ | ||
| Handles documents with empty or null array fields. | ||
|
|
||
| Input document:: | ||
|
|
||
| { "tags": [] } | ||
|
|
||
| PPL query:: | ||
|
|
||
| os> source=logs | mvexpand tags | ||
| fetched rows / total rows = 0/0 | ||
| +------+ | ||
| | tags | | ||
| +------+ | ||
| +------+ | ||
|
|
||
| Input document:: | ||
|
|
||
| { "tags": null } | ||
|
|
||
| PPL query:: | ||
|
|
||
| os> source=logs | mvexpand tags | ||
| fetched rows / total rows = 0/0 | ||
| +------+ | ||
| | tags | | ||
| +------+ | ||
| +------+ | ||
|
|
||
| Example 4: Non-array Field | ||
| -------------------------- | ||
| If the field is a single value (not an array), mvexpand returns the value as-is. | ||
|
|
||
| Input document:: | ||
|
|
||
| { "tags": "error" } | ||
|
|
||
| PPL query:: | ||
|
|
||
| os> source=logs | mvexpand tags | ||
| fetched rows / total rows = 1/1 | ||
| +-------+ | ||
| | tags | | ||
| +-------+ | ||
| | error | | ||
| +-------+ | ||
|
|
||
| Example 5: Large Arrays and Memory Limits | ||
| ---------------------------------------- | ||
| If an array exceeds configured memory/resource limits, mvexpand returns an error. | ||
|
||
|
|
||
| Input document:: | ||
|
|
||
| { "ids": [1, 2, ..., 100000] } | ||
|
|
||
| PPL query:: | ||
|
|
||
| os> source=docs | mvexpand ids | ||
| Error: Memory/resource limit exceeded while expanding field 'ids'. Please reduce the array size or specify a limit. | ||
|
|
||
| Example 6: Multiple Fields (Limitation) | ||
| --------------------------------------- | ||
| mvexpand only supports expanding one field per command. To expand multiple fields, use multiple mvexpand commands or document the limitation. | ||
|
|
||
| PPL query:: | ||
|
|
||
| os> source=docs | mvexpand a | mvexpand b | ||
|
|
||
| Example 7: Edge Case - Field Missing | ||
| ------------------------------------ | ||
| If the field does not exist in a document, no row is produced for that document. | ||
|
|
||
| Input document:: | ||
|
|
||
| { "other": [1,2] } | ||
|
|
||
| PPL query:: | ||
|
|
||
| os> source=docs | mvexpand tags | ||
| fetched rows / total rows = 0/0 | ||
| +------+ | ||
| | tags | | ||
| +------+ | ||
| +------+ | ||
|
|
||
| --- | ||
Uh oh!
There was an error while loading. Please reload this page.