Skip to content

Commit

Permalink
(#3) Added faceted search
Browse files Browse the repository at this point in the history
  • Loading branch information
SiroDiaz committed Jun 19, 2019
1 parent e2b882a commit 7d17699
Show file tree
Hide file tree
Showing 3 changed files with 83 additions and 11 deletions.
36 changes: 36 additions & 0 deletions __tests__/statements/select_statement.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,4 +227,40 @@ describe('Tests for select queries', () => {

expect(compiledQuery).toBe(expectedQuery);
});

it('selects with just one facet statement', () => {
const compiledQuery = new QueryBuilder(conn)
.select('user_id', 'product_id', Expression.raw('SUM(product_price) as total').getExpression())
.from('rt_sales')
.facet((f) => {
return f
.fields(['category_id'])
.by(['category_id'])
})
.generate();
const expectedQuery = `SELECT user_id, product_id, SUM(product_price) as total FROM rt_sales FACET category_id BY category_id`;

expect(compiledQuery).toBe(expectedQuery);
});

it('selects with just one facet statement', () => {
const compiledQuery = new QueryBuilder(conn)
.select('user_id', 'product_id', Expression.raw('SUM(product_price) as total').getExpression())
.from('rt_sales')
.facet((f) => {
return f
.fields(['category_id'])
.by(['category_id'])
})
.facet((f) => {
return f
.field('brand_id')
.orderBy(Expression.raw('facet()'))
.limit(5)
})
.generate();
const expectedQuery = `SELECT user_id, product_id, SUM(product_price) as total FROM rt_sales FACET category_id BY category_id FACET brand_id ORDER BY facet() DESC LIMIT 5`;

expect(compiledQuery).toBe(expectedQuery);
});
});
52 changes: 41 additions & 11 deletions src/Statements/SelectStatement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import WhereStatement from './statement_expressions/WhereStatement';
import StatementBuilderBase from './StatementBuilderBase';
import OptionExprStatement from './statement_expressions/OptionExprStatement';
import FacetStatement from './FacetStatement';
import Expression from './Expression';

/**
SELECT
Expand All @@ -36,6 +37,7 @@ export default class SelectStatement {
protected orderByFields: OrderByExprStatement[] = [];
protected limitExpr: LimitExprStatement;
protected optionExprs: OptionExprStatement[] = [];
protected facetExprs: FacetStatement[] = [];

public constructor(connection: ClientInterface, ...fields: string[]) {
this.connection = connection;
Expand All @@ -54,35 +56,54 @@ export default class SelectStatement {
* @param operator
* @param value
*/
public where(columnExpr: string, operator: string, value?: any): SelectStatement {
public where(columnExpr: string | Expression, operator: string, value?: any): SelectStatement {
if (value === undefined) {
value = operator;
operator = '=';
}

const condition = new WhereStatement(columnExpr, operator, value);
let condition: WhereStatement = null;
if (columnExpr instanceof Expression) {
condition = new WhereStatement(columnExpr.getExpression(), operator, value);
} else {
condition = new WhereStatement(columnExpr, operator, value);
}
this.whereConditions = [...this.whereConditions, condition];

return this;
}

public whereIn(column: string, values: any[]) {
const condition = new WhereStatement(column, 'IN', values);
public whereIn(column: string | Expression, values: any[]) {
let condition: WhereStatement = null;
if (column instanceof Expression) {
condition = new WhereStatement(column.getExpression(), 'IN', values);
} else {
condition = new WhereStatement(column, 'IN', values);
}
this.whereConditions = [...this.whereConditions, condition];

return this;
}

public whereNotIn(column: string, values: any[]) {
const condition = new WhereStatement(column, 'NOT IN', values);
public whereNotIn(column: string | Expression, values: any[]) {
let condition: WhereStatement = null;
if (column instanceof Expression) {
condition = new WhereStatement(column.getExpression(), 'NOT IN', values);
} else {
condition = new WhereStatement(column, 'NOT IN', values);
}
this.whereConditions = [...this.whereConditions, condition];

return this;
}

public between(column: string, value1: any, value2: any) {
const condtion = new WhereStatement(column, 'BETWEEN', [value1, value2]);
this.whereConditions = [...this.whereConditions, condtion];
public between(column: string | Expression, value1: any, value2: any) {
let condition: WhereStatement = null;
if (column instanceof Expression) {
condition = new WhereStatement(column.getExpression(), 'BETWEEN', [value1, value2]);
} else {
condition = new WhereStatement(column, 'BETWEEN', [value1, value2]);
}
this.whereConditions = [...this.whereConditions, condition];

return this;
}
Expand Down Expand Up @@ -192,7 +213,8 @@ export default class SelectStatement {

public facet(cb) {
let values = [];
values = [...values, cb.apply(this, [new FacetStatement(this.connection)])];
values = [...this.facetExprs, cb.apply(this, [new FacetStatement(this.connection)])];
this.facetExprs = values;

return this;
}
Expand Down Expand Up @@ -247,6 +269,14 @@ export default class SelectStatement {
statement += ` OPTION ${this.optionExprs.map((option) => option.build()).join(',')}`;
}

if (this.facetExprs.length) {
let facetStatement: string = '';
facetStatement = this.facetExprs.map((facet) => {
return ` FACET ${facet.build()}`;
}).join('');
statement += facetStatement;
}

return statement;
}

Expand Down
6 changes: 6 additions & 0 deletions src/Statements/statement_expressions/MatchStatement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ import StatementBuilderBase from '../StatementBuilderBase';

export default class MatchStatement implements StatementBuilderBase {
protected parts: object[];

/**
* List of characters that must be escaped for full-text search in SphinxQL:
* ! " $ ' ( ) - / < @ \ ^ | ~
* More info at: https://docs.manticoresearch.com/latest/html/searching/escaping_in_queries.html
*/
protected escapeChars: object = {
'\\': '\\\\',
'(' : '\(',
Expand Down

0 comments on commit 7d17699

Please sign in to comment.