Usando o modelo do Construtor de Consultas
Angular Construtor de Consultas fornece um modelo de formato JSON serializável/desserializável, facilitando a criação de consultas SQL.
Visão geral
Este exemplo Angular Construtor de Consultas demonstra como a IgxQueryBuilderComponent
árvore de expressão pode ser usada para solicitar dados de um ponto de extremidade Northwind WebAPI e defini-lo como uma fonte de IgxGridComponent
dados.
Query Builder Model
Para definir uma árvore de expressão como o IgxQueryBuilderComponent
, você precisa definir a FilteringExpressionsTree
. Cada FilteringExpressionsTree
um deve ter uma lógica de filtragem que represente como um registro de dados deve ser resolvido na árvore e, dependendo do caso de uso, você pode passar um nome de campo, nome de entidade e uma matriz de campos de retorno. Se todos os campos em uma determinada entidade devem ser retornados, a returnFields
propriedade pode ser definida como ['*']:
const tree = new FilteringExpressionsTree(FilteringLogic.And, undefined, 'Entity A', ['*']);
Uma vez que a raiz FilteringExpressionsTree
é criada, a adição de condições, grupos ou subconsultas, pode ser feita definindo sua filteringOperands
propriedade como uma matriz de IFilteringExpression
(expressão única ou um grupo) ou IFilteringExpressionsTree
(subconsulta). Cada IFilteringExpression
um e IFilteringExpressionsTree
deve ter um fieldName
que é o nome da coluna em que a expressão de filtragem é colocada e a condition
do tipo IFilteringOperation
ou a conditionName
. Se necessário, você também pode definir a,of searchVal
searchTree
type IExpressionTree
e ignoreCase
properties.
- Definindo uma expressão simples:
tree.filteringOperands.push({
fieldName: 'Name',
conditionName: IgxStringFilteringOperand.instance().condition('endsWith').name,
searchVal: 'a'
});
- Definindo um grupo de expressões:
const group = new FilteringExpressionsTree(FilteringLogic.Or, undefined, 'Entity A', ['*']);
group.filteringOperands.push({
fieldName: 'Name',
conditionName: IgxStringFilteringOperand.instance().condition('endsWith').name,
searchVal: 'a'
});
group.filteringOperands.push({
fieldName: 'DateTime created',
conditionName: IgxDateFilteringOperand.instance().condition('today').name
});
tree.filteringOperands.push(group);
- Definindo uma subconsulta:
const innerTree = new FilteringExpressionsTree(FilteringLogic.And, undefined, 'Entity B', ['Number']);
innerTree.filteringOperands.push({
fieldName: 'Number',
conditionName: 'equals',
searchVal: 123
});
tree.filteringOperands.push({
fieldName: 'Id',
conditionName: 'inQuery',
searchTree: innerTree
});
O modelo pode ser serializado/desserializado no formato JSON, tornando-o facilmente transferível entre cliente e servidor:
JSON.stringify(tree, null, 2);
Using Sub-Queries
No contexto do IgxQueryBuilderComponent
o DENTRO / NÃO DENTRO operadores são usados com a funcionalidade de subconsulta recém-exposta no ONDE cláusula.
Note
Uma subconsulta é uma consulta aninhada dentro de outra consulta usada para recuperar dados que serão usados como condição para a consulta externa.
Selecionar o operador IN / NOT-IN em um FilteringExpression
criaria uma subconsulta. Depois de escolher uma entidade e uma coluna a serem retornadas, ele verifica se o valor na coluna especificada na consulta externa corresponde ou não a qualquer um dos valores retornados pela subconsulta.
A seguinte árvore de expressão:
const innerTree = new FilteringExpressionsTree(FilteringLogic.And, undefined, 'Products', ['supplierId']);
innerTree.filteringOperands.push({
fieldName: 'supplierId',
conditionName: IgxNumberFilteringOperand.instance().condition('greaterThan').name,
searchVal: 10
});
const tree = new FilteringExpressionsTree(FilteringLogic.And, undefined, 'Suppliers', ['supplierId']);
tree.filteringOperands.push({
fieldName: 'supplierId',
conditionName: IgxStringFilteringOperand.instance().condition('inQuery').name,
searchTree: innerTree
});
Pode ser serializado chamando:
JSON.stringify(tree, null, 2);
Isso seria transferido como:
{
"filteringOperands": [
{
"fieldName": "supplierId",
"condition": {
"name": "inQuery",
"isUnary": false,
"isNestedQuery": true,
"iconName": "in"
},
"conditionName": "inQuery",
"searchVal": null,
"searchTree": {
"filteringOperands": [
{
"fieldName": "supplierId",
"condition": {
"name": "greaterThan",
"isUnary": false,
"iconName": "filter_greater_than"
},
"conditionName": "greaterThan",
"searchVal": 10,
"searchTree": null
}
],
"operator": 0,
"entity": "Suppliers",
"returnFields": [
"supplierId"
]
}
}
],
"operator": 0,
"entity": "Products",
"returnFields": [
"supplierId"
]
}
SQL Example
Vamos dar uma olhada em um exemplo prático de como o Ignite UI for Angular Query Builder Component pode ser usado para criar consultas SQL.
Na amostra abaixo temos 3 entities
com nomes 'Fornecedores', 'Categorias' e 'Produtos'.
Digamos que queremos encontrar todos os fornecedores que fornecem produtos que pertencem à categoria 'Bebidas'. Como os dados são distribuídos em todas as entidades, podemos aproveitar o operador IN e realizar a tarefa criando subconsultas. Cada subconsulta é representada por um FilteringExpressionsTree
e pode ser convertida em uma consulta SQL por meio do transformExpressionTreeToSqlQuery(tree: IExpressionTree)
método.
Primeiro, criamos um categoriesTree
que retornará o categoryId
para o registro onde name
está Beverages
. Esta é a subconsulta mais interna:
const categoriesTree = new FilteringExpressionsTree(0, undefined, 'Categories', ['categoryId']);
categoriesTree.filteringOperands.push({
fieldName: 'name',
conditionName: IgxStringFilteringOperand.instance().condition('equals').name,
searchVal: 'Beverages'
});
A consulta SQL correspondente para isso FilteringExpressionsTree
terá a seguinte aparência:
SELECT categoryId FROM Categories WHERE name = 'Beverages'
Em seguida, criamos um productsTree
que retornará o supplierId
campo do categoriesTree
para os registros em que o categoryId
corresponde ao categoryId
retornado pela subconsulta mais interna. Fazemos isso definindo a inQuery
condição e o relevante searchTree
. Esta é a subconsulta do meio:
const productsTree = new FilteringExpressionsTree(0, undefined, 'Products', ['supplierId']);
productsTree.filteringOperands.push({
fieldName: 'categoryId',
conditionName: IgxStringFilteringOperand.instance().condition('inQuery').name,
searchTree: categoriesTree
});
Este é o estado atualizado da consulta SQL:
SELECT supplierId FROM Products WHERE categoryId IN (
SELECT categoryId FROM Categories WHERE name = 'Beverages'
)
Por fim, criamos um suppliersTree
que retornará todos os campos da Suppliers
entidade em que correspondem a supplierId
qualquer um dos supplierId
s retornados pela subconsulta do meio. Esta é a consulta mais externa:
const suppliersTree = new FilteringExpressionsTree(0, undefined, 'Suppliers', ['*']);
suppliersTree.filteringOperands.push({
fieldName: 'supplierId',
conditionName: IgxStringFilteringOperand.instance().condition('inQuery').name,
searchTree: productsTree
});
Nossa consulta SQL agora está concluída:
SELECT * FROM Suppliers WHERE supplierId IN (
SELECT supplierId FROM Products WHERE categoryId IN (
SELECT categoryId FROM Categories WHERE name = 'Beverages'
)
)
Agora podemos definir a expressionsTree
propriedade do IgxQueryBuilderComponent
para suppliersTree
. Além disso, cada alteração na consulta aciona uma nova solicitação para o endpoint e os dados resultantes mostrados na grade são atualizados.