Adding built-in sorting capability to _cat apis. (#20658)

* Adding built-in sorting capability to _cat apis.

Closes #16975

* addressing pr comments

* changing value types back to original implementation and fixing cosmetic issues

* Changing compareTo, hashCode of value types to a better implementation

* Changed value compareTos to use Double.compare instead of if statements + fixed some failed unit tests
This commit is contained in:
Alexander Lin 2016-10-11 09:29:22 -07:00 committed by Nik Everett
parent 3b578db365
commit 10ddcc4616
37 changed files with 714 additions and 32 deletions

View File

@ -30,8 +30,6 @@ import java.util.concurrent.TimeUnit;
import static java.util.Collections.emptyMap;
/**
*/
public class Table {
private List<Cell> headers = new ArrayList<>();
@ -197,6 +195,22 @@ public class Table {
return null;
}
public Map<String, String> getAliasMap() {
Map<String, String> headerAliasMap = new HashMap<>();
for (int i = 0; i < headers.size(); i++) {
Cell headerCell = headers.get(i);
String headerName = headerCell.value.toString();
if (headerCell.attr.containsKey("alias")) {
String[] aliases = Strings.splitStringByCommaToArray(headerCell.attr.get("alias"));
for (String alias : aliases) {
headerAliasMap.put(alias, headerName);
}
}
headerAliasMap.put(headerName, headerName);
}
return headerAliasMap;
}
public static class Cell {
public final Object value;
public final Map<String, String> attr;

View File

@ -269,4 +269,4 @@ public enum ByteSizeUnit implements Writeable {
public static ByteSizeUnit readFrom(StreamInput in) throws IOException {
return ByteSizeUnit.fromId(in.readVInt());
}
}
}

View File

@ -29,7 +29,7 @@ import java.io.IOException;
import java.util.Locale;
import java.util.Objects;
public class ByteSizeValue implements Writeable {
public class ByteSizeValue implements Writeable, Comparable<ByteSizeValue> {
private final long size;
private final ByteSizeUnit unit;
@ -191,15 +191,18 @@ public class ByteSizeValue implements Writeable {
return false;
}
ByteSizeValue sizeValue = (ByteSizeValue) o;
return getBytes() == sizeValue.getBytes();
return compareTo((ByteSizeValue) o) == 0;
}
@Override
public int hashCode() {
int result = Long.hashCode(size);
result = 31 * result + (unit != null ? unit.hashCode() : 0);
return result;
return Double.hashCode(((double) size) * unit.toBytes(1));
}
@Override
public int compareTo(ByteSizeValue other) {
double thisValue = ((double) size) * unit.toBytes(1);
double otherValue = ((double) other.size) * other.unit.toBytes(1);
return Double.compare(thisValue, otherValue);
}
}

View File

@ -27,7 +27,7 @@ import org.elasticsearch.common.io.stream.Writeable;
import java.io.IOException;
public class SizeValue implements Writeable {
public class SizeValue implements Writeable, Comparable<SizeValue> {
private final long size;
private final SizeUnit sizeUnit;
@ -201,18 +201,18 @@ public class SizeValue implements Writeable {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SizeValue sizeValue = (SizeValue) o;
if (size != sizeValue.size) return false;
if (sizeUnit != sizeValue.sizeUnit) return false;
return true;
return compareTo((SizeValue) o) == 0;
}
@Override
public int hashCode() {
int result = Long.hashCode(size);
result = 31 * result + (sizeUnit != null ? sizeUnit.hashCode() : 0);
return result;
return Double.hashCode(((double) size) * sizeUnit.toSingles(1));
}
@Override
public int compareTo(SizeValue other) {
double thisValue = ((double) size) * sizeUnit.toSingles(1);
double otherValue = ((double) other.size) * other.sizeUnit.toSingles(1);
return Double.compare(thisValue, otherValue);
}
}

View File

@ -39,7 +39,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
public class TimeValue implements Writeable {
public class TimeValue implements Writeable, Comparable<TimeValue> {
/** How many nano-seconds in one milli-second */
public static final long NSEC_PER_MSEC = TimeUnit.NANOSECONDS.convert(1, TimeUnit.MILLISECONDS);
@ -381,17 +381,22 @@ public class TimeValue implements Writeable {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
TimeValue timeValue = (TimeValue) o;
return timeUnit.toNanos(duration) == timeValue.timeUnit.toNanos(timeValue.duration);
return this.compareTo(((TimeValue) o)) == 0;
}
@Override
public int hashCode() {
long normalized = timeUnit.toNanos(duration);
return Long.hashCode(normalized);
return Double.hashCode(((double) duration) * timeUnit.toNanos(1));
}
public static long nsecToMSec(long ns) {
return ns / NSEC_PER_MSEC;
}
@Override
public int compareTo(TimeValue timeValue) {
double thisValue = ((double) duration) * timeUnit.toNanos(1);
double otherValue = ((double) timeValue.duration) * timeValue.timeUnit.toNanos(1);
return Double.compare(thisValue, otherValue);
}
}

View File

@ -38,8 +38,12 @@ import org.elasticsearch.rest.RestStatus;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
public class RestTable {
@ -59,13 +63,13 @@ public class RestTable {
List<DisplayHeader> displayHeaders = buildDisplayHeaders(table, request);
builder.startArray();
for (int row = 0; row < table.getRows().size(); row++) {
List<Integer> rowOrder = getRowOrder(table, request);
for (Integer row : rowOrder) {
builder.startObject();
for (DisplayHeader header : displayHeaders) {
builder.field(header.display, renderValue(request, table.getAsMap().get(header.name).get(row).value));
}
builder.endObject();
}
builder.endArray();
return new BytesRestResponse(RestStatus.OK, builder);
@ -92,7 +96,10 @@ public class RestTable {
}
out.append("\n");
}
for (int row = 0; row < table.getRows().size(); row++) {
List<Integer> rowOrder = getRowOrder(table, request);
for (Integer row: rowOrder) {
for (int col = 0; col < headers.size(); col++) {
DisplayHeader header = headers.get(col);
boolean isLastColumn = col == lastHeader;
@ -107,6 +114,38 @@ public class RestTable {
return new BytesRestResponse(RestStatus.OK, BytesRestResponse.TEXT_CONTENT_TYPE, bytesOut.bytes());
}
static List<Integer> getRowOrder(Table table, RestRequest request) {
String[] columnOrdering = request.paramAsStringArray("s", null);
List<Integer> rowOrder = new ArrayList<>();
for (int i = 0; i < table.getRows().size(); i++) {
rowOrder.add(i);
}
if (columnOrdering != null) {
Map<String, String> headerAliasMap = table.getAliasMap();
List<ColumnOrderElement> ordering = new ArrayList<>();
for (int i = 0; i < columnOrdering.length; i++) {
String columnHeader = columnOrdering[i];
boolean reverse = false;
if (columnHeader.endsWith(":desc")) {
columnHeader = columnHeader.substring(0, columnHeader.length() - ":desc".length());
reverse = true;
} else if (columnHeader.endsWith(":asc")) {
columnHeader = columnHeader.substring(0, columnHeader.length() - ":asc".length());
}
if (headerAliasMap.containsKey(columnHeader)) {
ordering.add(new ColumnOrderElement(headerAliasMap.get(columnHeader), reverse));
} else {
throw new UnsupportedOperationException(
String.format(Locale.ROOT, "Unable to sort by unknown sort key `%s`", columnHeader));
}
}
Collections.sort(rowOrder, new TableIndexComparator(table, ordering));
}
return rowOrder;
}
static List<DisplayHeader> buildDisplayHeaders(Table table, RestRequest request) {
List<DisplayHeader> display = new ArrayList<>();
if (request.hasParam("h")) {
@ -368,4 +407,71 @@ public class RestTable {
this.display = display;
}
}
static class TableIndexComparator implements Comparator<Integer> {
private final Table table;
private final int maxIndex;
private final List<ColumnOrderElement> ordering;
TableIndexComparator(Table table, List<ColumnOrderElement> ordering) {
this.table = table;
this.maxIndex = table.getRows().size();
this.ordering = ordering;
}
private int compareCell(Object o1, Object o2) {
if (o1 == null && o2 == null) {
return 0;
} else if (o1 == null) {
return -1;
} else if (o2 == null) {
return 1;
} else {
if (o1 instanceof Comparable && o1.getClass().equals(o2.getClass())) {
return ((Comparable) o1).compareTo(o2);
} else {
return o1.toString().compareTo(o2.toString());
}
}
}
@Override
public int compare(Integer rowIndex1, Integer rowIndex2) {
if (rowIndex1 < maxIndex && rowIndex1 >= 0 && rowIndex2 < maxIndex && rowIndex2 >= 0) {
Map<String, List<Table.Cell>> tableMap = table.getAsMap();
for (ColumnOrderElement orderingElement : ordering) {
String column = orderingElement.getColumn();
if (tableMap.containsKey(column)) {
int comparison = compareCell(tableMap.get(column).get(rowIndex1).value,
tableMap.get(column).get(rowIndex2).value);
if (comparison != 0) {
return orderingElement.isReversed() ? -1 * comparison : comparison;
}
}
}
return 0;
} else {
throw new AssertionError(String.format(Locale.ENGLISH, "Invalid comparison of indices (%s, %s): Table has %s rows.",
rowIndex1, rowIndex2, table.getRows().size()));
}
}
}
static class ColumnOrderElement {
private final String column;
private final boolean reverse;
public ColumnOrderElement(String column, boolean reverse) {
this.column = column;
this.reverse = reverse;
}
public String getColumn() {
return column;
}
public boolean isReversed() {
return reverse;
}
}
}

View File

@ -200,6 +200,19 @@ public class TableTests extends ESTestCase {
}
public void testAliasMap() {
Table table = new Table();
table.startHeaders();
table.addCell("asdf", "alias:a");
table.addCell("ghij", "alias:g,h");
table.endHeaders();
Map<String, String> aliasMap = table.getAliasMap();
assertEquals(5, aliasMap.size());
assertEquals("asdf", aliasMap.get("a"));
assertEquals("ghij", aliasMap.get("g"));
assertEquals("ghij", aliasMap.get("h"));
}
private Table getTableWithHeaders() {
Table table = new Table();
table.startHeaders();

View File

@ -170,13 +170,52 @@ public class ByteSizeValueTests extends ESTestCase {
}
}
public void testCompareEquality() {
long firstRandom = randomPositiveLong();
ByteSizeUnit randomUnit = randomFrom(ByteSizeUnit.values());
ByteSizeValue firstByteValue = new ByteSizeValue(firstRandom, randomUnit);
ByteSizeValue secondByteValue = new ByteSizeValue(firstRandom, randomUnit);
assertEquals(0, firstByteValue.compareTo(secondByteValue));
}
public void testCompareValue() {
long firstRandom = randomPositiveLong();
long secondRandom = randomValueOtherThan(firstRandom, ESTestCase::randomPositiveLong);
ByteSizeUnit unit = randomFrom(ByteSizeUnit.values());
ByteSizeValue firstByteValue = new ByteSizeValue(firstRandom, unit);
ByteSizeValue secondByteValue = new ByteSizeValue(secondRandom, unit);
assertEquals(firstRandom > secondRandom, firstByteValue.compareTo(secondByteValue) > 0);
assertEquals(secondRandom > firstRandom, secondByteValue.compareTo(firstByteValue) > 0);
}
public void testCompareUnits() {
long number = randomPositiveLong();
ByteSizeUnit randomUnit = randomValueOtherThan(ByteSizeUnit.PB, ()->randomFrom(ByteSizeUnit.values()));
ByteSizeValue firstByteValue = new ByteSizeValue(number, randomUnit);
ByteSizeValue secondByteValue = new ByteSizeValue(number, ByteSizeUnit.PB);
assertTrue(firstByteValue.compareTo(secondByteValue) < 0);
assertTrue(secondByteValue.compareTo(firstByteValue) > 0);
}
public void testEdgeCompare() {
ByteSizeValue maxLongValuePB = new ByteSizeValue(Long.MAX_VALUE, ByteSizeUnit.PB);
ByteSizeValue maxLongValueB = new ByteSizeValue(Long.MAX_VALUE, ByteSizeUnit.BYTES);
assertTrue(maxLongValuePB.compareTo(maxLongValueB) > 0);
}
public void testConversionHashCode() {
ByteSizeValue firstValue = new ByteSizeValue(randomIntBetween(0, Integer.MAX_VALUE), ByteSizeUnit.GB);
ByteSizeValue secondValue = new ByteSizeValue(firstValue.getBytes(), ByteSizeUnit.BYTES);
assertEquals(firstValue.hashCode(), secondValue.hashCode());
}
public void testSerialization() throws IOException {
ByteSizeValue byteSizeValue = new ByteSizeValue(randomPositiveLong(), randomFrom(ByteSizeUnit.values()));
try (BytesStreamOutput out = new BytesStreamOutput()) {
byteSizeValue.writeTo(out);
try (StreamInput in = out.bytes().streamInput()) {
ByteSizeValue deserializedByteSizeValue = new ByteSizeValue(in);
assertEquals(byteSizeValue, deserializedByteSizeValue);
assertEquals(byteSizeValue.getBytes(), deserializedByteSizeValue.getBytes());
}
}
}

View File

@ -67,4 +67,37 @@ public class SizeValueTests extends ESTestCase {
assertThat(e.getMessage(), containsString("may not be negative"));
}
}
public void testCompareEquality() {
long randomValue = randomPositiveLong();
SizeUnit randomUnit = randomFrom(SizeUnit.values());
SizeValue firstValue = new SizeValue(randomValue, randomUnit);
SizeValue secondValue = new SizeValue(randomValue, randomUnit);
assertEquals(0, firstValue.compareTo(secondValue));
}
public void testCompareValue() {
long firstRandom = randomPositiveLong();
long secondRandom = randomValueOtherThan(firstRandom, ESTestCase::randomPositiveLong);
SizeUnit unit = randomFrom(SizeUnit.values());
SizeValue firstSizeValue = new SizeValue(firstRandom, unit);
SizeValue secondSizeValue = new SizeValue(secondRandom, unit);
assertEquals(firstRandom > secondRandom, firstSizeValue.compareTo(secondSizeValue) > 0);
assertEquals(secondRandom > firstRandom, secondSizeValue.compareTo(firstSizeValue) > 0);
}
public void testCompareUnits() {
long number = randomPositiveLong();
SizeUnit randomUnit = randomValueOtherThan(SizeUnit.PETA, ()->randomFrom(SizeUnit.values()));
SizeValue firstValue = new SizeValue(number, randomUnit);
SizeValue secondValue = new SizeValue(number, SizeUnit.PETA);
assertTrue(firstValue.compareTo(secondValue) < 0);
assertTrue(secondValue.compareTo(firstValue) > 0);
}
public void testConversionHashCode() {
SizeValue firstValue = new SizeValue(randomIntBetween(0, Integer.MAX_VALUE), SizeUnit.GIGA);
SizeValue secondValue = new SizeValue(firstValue.getSingles(), SizeUnit.SINGLE);
assertEquals(firstValue.hashCode(), secondValue.hashCode());
}
}

View File

@ -224,4 +224,37 @@ public class TimeValueTests extends ESTestCase {
assertEquals("36h", new TimeValue(36, TimeUnit.HOURS).getStringRep());
assertEquals("1000d", new TimeValue(1000, TimeUnit.DAYS).getStringRep());
}
public void testCompareEquality() {
long randomLong = randomPositiveLong();
TimeUnit randomUnit = randomFrom(TimeUnit.values());
TimeValue firstValue = new TimeValue(randomLong, randomUnit);
TimeValue secondValue = new TimeValue(randomLong, randomUnit);
assertEquals(0, firstValue.compareTo(secondValue));
}
public void testCompareValue() {
long firstRandom = randomPositiveLong();
long secondRandom = randomValueOtherThan(firstRandom, ESTestCase::randomPositiveLong);
TimeUnit unit = randomFrom(TimeUnit.values());
TimeValue firstValue = new TimeValue(firstRandom, unit);
TimeValue secondValue = new TimeValue(secondRandom, unit);
assertEquals(firstRandom > secondRandom, firstValue.compareTo(secondValue) > 0);
assertEquals(secondRandom > firstRandom, secondValue.compareTo(firstValue) > 0);
}
public void testCompareUnits() {
long number = randomPositiveLong();
TimeUnit randomUnit = randomValueOtherThan(TimeUnit.DAYS, ()->randomFrom(TimeUnit.values()));
TimeValue firstValue = new TimeValue(number, randomUnit);
TimeValue secondValue = new TimeValue(number, TimeUnit.DAYS);
assertTrue(firstValue.compareTo(secondValue) < 0);
assertTrue(secondValue.compareTo(firstValue) > 0);
}
public void testConversionHashCode() {
TimeValue firstValue = new TimeValue(randomIntBetween(0, Integer.MAX_VALUE), TimeUnit.MINUTES);
TimeValue secondValue = new TimeValue(firstValue.getSeconds(), TimeUnit.SECONDS);
assertEquals(firstValue.hashCode(), secondValue.hashCode());
}
}

View File

@ -23,12 +23,12 @@ import org.elasticsearch.common.Table;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.rest.AbstractRestChannel;
import org.elasticsearch.rest.RestResponse;
import org.elasticsearch.rest.action.cat.RestTable;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.rest.FakeRestRequest;
import org.junit.Before;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@ -62,11 +62,13 @@ public class RestTableTests extends ESTestCase {
" invalidAliasesBulk: \"foo\"\n" +
" timestamp: \"foo\"\n" +
" epoch: \"foo\"\n";
private Table table = new Table();
private FakeRestRequest restRequest = new FakeRestRequest();
private Table table;
private FakeRestRequest restRequest;
@Before
public void setup() {
restRequest = new FakeRestRequest();
table = new Table();
table.startHeaders();
table.addCell("bulk.foo", "alias:f;desc:foo");
table.addCell("bulk.bar", "alias:b;desc:bar");
@ -146,6 +148,110 @@ public class RestTableTests extends ESTestCase {
assertThat(headerNames, not(hasItem("epoch")));
}
public void testCompareRow() {
Table table = new Table();
table.startHeaders();
table.addCell("compare");
table.endHeaders();
for (Integer i : Arrays.asList(1,2,1)) {
table.startRow();
table.addCell(i);
table.endRow();
}
RestTable.TableIndexComparator comparator = new RestTable.TableIndexComparator(table,
Collections.singletonList(new RestTable.ColumnOrderElement("compare", false)));
assertTrue(comparator.compare(0,1) < 0);
assertTrue(comparator.compare(0,2) == 0);
assertTrue(comparator.compare(1,2) > 0);
RestTable.TableIndexComparator reverseComparator = new RestTable.TableIndexComparator(table,
Collections.singletonList(new RestTable.ColumnOrderElement("compare", true)));
assertTrue(reverseComparator.compare(0,1) > 0);
assertTrue(reverseComparator.compare(0,2) == 0);
assertTrue(reverseComparator.compare(1,2) < 0);
}
public void testRowOutOfBounds() {
Table table = new Table();
table.startHeaders();
table.addCell("compare");
table.endHeaders();
RestTable.TableIndexComparator comparator = new RestTable.TableIndexComparator(table,
Collections.singletonList(new RestTable.ColumnOrderElement("compare", false)));
Error e = expectThrows(AssertionError.class, () -> {
comparator.compare(0,1);
});
assertEquals("Invalid comparison of indices (0, 1): Table has 0 rows.", e.getMessage());
}
public void testUnknownHeader() {
Table table = new Table();
table.startHeaders();
table.addCell("compare");
table.endHeaders();
restRequest.params().put("s", "notaheader");
Exception e = expectThrows(UnsupportedOperationException.class, () -> RestTable.getRowOrder(table, restRequest));
assertEquals("Unable to sort by unknown sort key `notaheader`", e.getMessage());
}
public void testAliasSort() {
Table table = new Table();
table.startHeaders();
table.addCell("compare", "alias:c;");
table.endHeaders();
List<Integer> comparisonList = Arrays.asList(3,1,2);
for (int i = 0; i < comparisonList.size(); i++) {
table.startRow();
table.addCell(comparisonList.get(i));
table.endRow();
}
restRequest.params().put("s", "c");
List<Integer> rowOrder = RestTable.getRowOrder(table, restRequest);
assertEquals(Arrays.asList(1,2,0), rowOrder);
}
public void testReversedSort() {
Table table = new Table();
table.startHeaders();
table.addCell("reversed");
table.endHeaders();
List<Integer> comparisonList = Arrays.asList(0, 1, 2);
for (int i = 0; i < comparisonList.size(); i++) {
table.startRow();
table.addCell(comparisonList.get(i));
table.endRow();
}
restRequest.params().put("s", "reversed:desc");
List<Integer> rowOrder = RestTable.getRowOrder(table, restRequest);
assertEquals(Arrays.asList(2,1,0), rowOrder);
}
public void testMultiSort() {
Table table = new Table();
table.startHeaders();
table.addCell("compare");
table.addCell("second.compare");
table.endHeaders();
List<Integer> comparisonList = Arrays.asList(3, 3, 2);
List<Integer> secondComparisonList = Arrays.asList(2, 1, 3);
for (int i = 0; i < comparisonList.size(); i++) {
table.startRow();
table.addCell(comparisonList.get(i));
table.addCell(secondComparisonList.get(i));
table.endRow();
}
restRequest.params().put("s", "compare,second.compare");
List<Integer> rowOrder = RestTable.getRowOrder(table, restRequest);
assertEquals(Arrays.asList(2,1,0), rowOrder);
restRequest.params().put("s", "compare:desc,second.compare");
rowOrder = RestTable.getRowOrder(table, restRequest);
assertEquals(Arrays.asList(1,0,2), rowOrder);
}
private RestResponse assertResponseContentType(Map<String, String> headers, String mediaType) throws Exception {
FakeRestRequest requestWithAcceptHeader = new FakeRestRequest.Builder().withHeaders(headers).build();
table.startRow();

View File

@ -175,6 +175,36 @@ For example:
--------------------------------------------------
// NOTCONSOLE
[float]
[[sort]]
=== Sort
Each of the commands accepts a query string parameter `s` which sorts the table by
the columns specified as the parameter value. Columns are specified either by name or by
alias, and are provided as a comma separated string. By default, sorting is done in
ascending fashion. Appending `:desc` to a column will invert the ordering for
that column. `:asc` is also accepted but exhibits the same behavior as the default sort order.
For example, with a sort string `s=column1,column2:desc,column3`, the table will be
sorted in ascending order by column1, in descending order by column2, and in ascending
order by column3.
[source,sh]
--------------------------------------------------
GET _cat/templates?v&s=order:desc,template
--------------------------------------------------
//CONSOLE
returns:
[source,sh]
--------------------------------------------------
name template order version
pizza_pepperoni *pepperoni* 2
sushi_california_roll *avocado* 1 1
pizza_hawaiian *pineapples* 1
--------------------------------------------------
--
include::cat/alias.asciidoc[]

View File

@ -33,6 +33,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -38,6 +38,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -33,6 +33,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -38,6 +38,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -29,6 +29,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"ts": {
"type": "boolean",
"description": "Set to false to disable timestamping",

View File

@ -12,6 +12,10 @@
"type": "boolean",
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
}
}
},

View File

@ -49,6 +49,10 @@
"description": "Set to true to return stats only for primary shards",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -29,6 +29,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -29,6 +29,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -29,6 +29,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -29,6 +29,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -27,6 +27,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -34,6 +34,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -30,6 +30,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -25,6 +25,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -33,6 +33,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -37,6 +37,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -41,6 +41,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -33,6 +33,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -34,6 +34,10 @@
"description": "Return help information",
"default": false
},
"s": {
"type": "list",
"description" : "Comma-separated list of column names or column aliases to sort by"
},
"v": {
"type": "boolean",
"description": "Verbose mode. Display column headers",

View File

@ -216,3 +216,46 @@
- \s+
$/
---
"Alias sorting":
- do:
indices.create:
index: test_index
body:
aliases:
test_alias: {}
my_alias: {}
- do:
indices.create:
index: other_index
body:
aliases:
other_alias: {}
- do:
cat.aliases:
h: [alias, index]
s: [index, alias]
- match:
$body: |
/^
other_alias \s+ other_index\n
my_alias \s+ test_index\n
test_alias \s+ test_index\n
$/
- do:
cat.aliases:
h: [alias, index]
s: [index, "a:desc"]
- match:
$body: |
/^
other_alias \s+ other_index\n
test_alias \s+ test_index\n
my_alias \s+ test_index\n
$/

View File

@ -157,3 +157,57 @@
- match:
$body: |
/^(ba(r|z) \n?){2}$/
---
"Test cat indices sort":
- do:
indices.create:
index: foo
body:
settings:
number_of_shards: "1"
number_of_replicas: "0"
- do:
indices.create:
index: bar
body:
settings:
number_of_shards: "1"
number_of_replicas: "0"
- do:
indices.create:
index: baz
body:
settings:
number_of_shards: "1"
number_of_replicas: "0"
- do:
indices.close:
index: bar
- do:
cat.indices:
h: [status, index]
s: [status, index]
- match:
$body: |
/^ close \s+ bar\n
open \s+ baz\n
open \s+ foo\n
$/
- do:
cat.indices:
h: [status, index]
s: [status, "index:desc"]
- match:
$body: |
/^ close \s+ bar\n
open \s+ foo\n
open \s+ baz\n
$/

View File

@ -43,3 +43,42 @@
/^ test_cat_repo_1\s+ fs\s*\n
test_cat_repo_2\s+ fs\s*\n
$/
---
"Test cat repositories sort":
- do:
snapshot.create_repository:
repository: test_cat_repo_1
body:
type: fs
settings:
location: "test_cat_repo_1_loc"
- do:
snapshot.create_repository:
repository: test_cat_repo_2
body:
type: fs
settings:
location: "test_cat_repo_2_loc"
- do:
cat.repositories:
s: [type, id]
- match:
$body: |
/^ test_cat_repo_1 \s+ fs \n
test_cat_repo_2 \s+ fs \n
$/
- do:
cat.repositories:
s: [type, "id:desc"]
- match:
$body: |
/^ test_cat_repo_2 \s+ fs \n
test_cat_repo_1 \s+ fs \n
$/

View File

@ -224,3 +224,40 @@
- match:
$body: |
/^(ba(r|z) \n?){2}$/
---
"Test cat shards sort":
- do:
indices.create:
index: foo
body:
settings:
number_of_shards: "1"
number_of_replicas: "0"
- do:
indices.create:
index: bar
body:
settings:
number_of_shards: "1"
number_of_replicas: "0"
- do:
index:
index: bar
type: type
body: { test: bar }
refresh: true
- do:
cat.shards:
h: [index, store]
s: [store]
- match:
$body: |
/^ foo \s+ (\d+|\d+[.]\d+)(kb|b)\n
bar \s+ (\d+|\d+[.]\d+)(kb|b)\n
$/

View File

@ -174,3 +174,50 @@
\n
$/
---
"Sort templates":
- do:
indices.put_template:
name: test
body:
order: 0
template: t*
settings:
number_of_shards: 1
number_of_replicas: 0
- do:
indices.put_template:
name: test_1
body:
order: 0
version: 1
template: te*
settings:
number_of_shards: 1
number_of_replicas: 0
- do:
cat.templates:
h: [name, template, version]
s: [version]
- match:
$body: |
/^
test \s+ t\* \s+\n
test_1 \s+ te\* \s+ 1\n
$/
- do:
cat.templates:
h: [name, template, version]
s: ["version:desc"]
- match:
$body: |
/^
test_1 \s+ te\* \s+ 1\n
test \s+ t\* \s+\n
$/