Skip to content

Instantly share code, notes, and snippets.

@stacey-gammon
Last active November 27, 2019 14:52
Show Gist options
  • Save stacey-gammon/3b9033da03701099779d1d2aabdf0155 to your computer and use it in GitHub Desktop.
Save stacey-gammon/3b9033da03701099779d1d2aabdf0155 to your computer and use it in GitHub Desktop.
class InMemoryTable extends IDataTable {
  // basic impl of all the funcs on an in memory table.
}

interface IDataTable {
  narrow(narrowingQuery: INarrowingQuery): IDataTable;
  selectColumns(columns: string[]): IDataTable;
  groupBy(aggs: Aggs): IDataTable;
  getFieldSuggestions(fieldPrefix: string): IDataTable;
  getValueSuggestions(field: string, valuePrefix: string): IDataTable;
  join(other: IDataTable, on: string): IDataTable;
  getRows(): string[][];??
}

class ESDataTable implements IDataTable {
  // Question - is this always up to date, or require a forced update?
  this.results;

  // Question - is this post index source set, or pre-index source (e.g. entire cluster).
  // Maybe if entire cluster, it's just null.  Do we need this at all?
  this.source;

  constructor(indexPattern: string) {
    this.source = indexPattern;
  }

  // Add narrowing fns
  narrow(narrower: INarrowingQuery) {
    this.narrowers.push(narrower);
    return this.execute();
  }
  
  // Add column selections
  selectColumns(columns: string[]): IDataTable {
    // add columns
    this.selectedColumns.concat(columns);
    return this.execute();
  }

  // Add aggregations
  groupBy(aggs: Aggs): IDataTable {
    this.addAggs(aggs);
    return this.execute();
  }

  getFieldSuggestions(fieldPrefix: string) {...}

  getValueSuggestions(field: string, valuePrefix) {...}

  execute() {
    // First, narrow. If this is all KQL that can be represented in ES Query DSL,
    // the resultTable will remain an ESDataTable.  As soon as a narrowing query
    // is encountered that can't be represented that way, it will switch to an
    // InMemoryDataTable. If another narrowing query is encountered that can
    // only run on ES data, it will once again be replaced by an ESDataTable
    // that is targeting the indexed in memory table.
    let resultTable = this;
    this.narrowers.forEach(narrower => {
      resultTable = narrower.narrow(resultTable));
    }
    // Then, apply aggs.  Haven't thought this one through...

    // return the results table.
    return resultTable;
  }

  async getRows() {
    if (!this.results) {
      this.results = search(this.toEsDsl());
    }
    return this.results;
  }

  join(other: IDataTable, joinOnColumn: string) {
    ...?
  }
}

class ITermsQuery extends INarrowingQuery {
  constructor(term, value) {..}
   narrow(table: IDataTable) {
      if (table.type === ESDSL) {
        table.addQueryDsl(this.toEsDsl())
     }  else if (table.type === EQL) {
       // we can add a terms query in EQL too
     } else {
       // We hit a new table type we don’t know about, or it’s in memory.
      // If we can execute this query in memory, lets do so, otherwise we could consider 
       // re-indexing into ES and executing the query that way (e.g. we probably don’t want to 
       // be in the business of duplicating all filter type logic in Kibana).
       table.toInMemoryDataTable().getRows.reduce(row => row.cell(this.term) === this.value);
      }
   }
}


// If we don’t want to bother parsing es sql, just return the InMemoryTable
esSql(..).selectColumns(...).groupBy(...)

// ESAggs can return the ESMemoryTable
esAggs(...).selectColumns(...).groupBy(...)

// Users can use a raw in InMemoryTable.
table(...).selectColumns(...).groupBy(...)
table(...).query(new TermsQuery(x, y))

esAggs(...).selectColumns(...).groupBy(...).query(new TermsQuery(x, y))


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment