Пространство имен Query
В аддоне ember-flexberry-data
экспортируется пространство имен Query, в котором содержатся классы для работы с языком запросов.
Для импорта пространства имен Query необходимо использовать следующий код:
import { Query } from 'ember-flexberry-data';
В пространстве имен Query содержится следующий перечень классов:
BaseAdapter
- базовый класс для адаптеров языка запросов, которые преобразуют объект запроса в запрос для конкретного типа бэкэнда.BaseBuilder
- базовый класс для построителя запросов.Builder
- класс для построения запросов (построитель запросов).Condition
- перечисление с логическими операциями для Query.ComplexPredicate.FilterOperator
- перечисление с операциями для Query.SimplePredicate.IndexedDbAdapter
- адаптер языка запросов для построения запросов к IndexedDB из объекта запроса.JsAdapter
- адаптер языка запросов для построения функций фильтраций JavaScript-массивов из объекта запроса.OdataAdapter
- адаптер языка запросов для построения запросов согласно спецификации OData из объекта запроса.OrderByClause
- класс для формирования order-by части запроса.BasePredicate
- базовый класс для классов предикатов.SimplePredicate
- класс для создания фильтра в запросе по значению атрибута и указанной операции.ComplexPredicate
- класс для создания фильтра в запросе из нескольких предикатов, объединенных логическими операциями.StringPredicate
- класс для создания фильтра в запросе по строковым полям.DetailPredicate
- класс для создания фильтра в запросе по детейловым объектам.DatePredicate
- класс для создания фильтра в запросе по полям с типом дата.NotPredicate
- класс для инверсии вложенного предиката.TruePredicate
- класс для создания фильтра с заведомо выполняемым условием.FalsePredicate
- класс для создания фильтра с заведомо невыполняемым условием.IsOfPredicate
- класс для создания фильтра в запросе по типу объекта данных.InPredicate
- класс для создания фильтра в запросе по значению атрибута, входящего в заданный список значени.createPredicate
- метод для создания предиката по заданным параметрам.
Пример использования классов из пространства имен:
let builder = new Query.Builder(store);
Для того, чтобы не писать везде в коде явно пространство имен, можно использовать следующую конструкцию языка JavaScript:
import { Query } from 'ember-flexberry-data';
const { Builder, FilterOperator } = Query;
let builder = new Builder(store, 'customer').where('firstName', FilterOperator.Eq, 'Vasya');
Query.Builder
Query.Builder
- класс для построения запроса.
Конструктор
Конструктор Query.Builder
может принимать 2 параметра: обязательный store
, и modelName
- наименование сущности запроса (наименование модели для вычитки).
let builder = new Query.Builder(store);
let builder = new Query.Builder(store, 'customer');
Вычитывание объекта по ключу
Метод byId
принимает параметр строку или число в качестве ключа объекта (GUID необходимо передавать в нижнем регистре).
let builder = new Query.Builder(this.store)
.from(modelName)
.selectByProjection(projectionName)
.byId('3087fbdc-273e-4bae-b440-071fd1eab1e0');
Наименование сущности
builder.from('employee');
Ограничение
Предикат - функция, возвращающая true
/false
.
Предикат может быть:
- Простым
- Сложным
- Строковым
- Детейловым
builder.where(Query.SomePredicate);
или
let builder = new Query.Builder(store, 'customer').where('firstName', Query.FilterOperator.Eq, 'Vasya');
Для мастера
let builder = new Query.Builder(store, 'customer').where('manager', Query.FilterOperator.Eq, '3bcc4730-9cc1-4237-a843-c4b1de881d7c');
Для поля мастера
let builder = new Query.Builder(store, 'customer').where('manager.firstName', Query.FilterOperator.Eq, 'Vasya');
cast
и другие OData-специфичные функции!Поступая так, вы привязываетесь в запросах к бэкэнду конкретного типа.
Язык же запросов создан для того, чтобы абстрагироваться от какого-либо типа бэкэнда.
При несоблюдении этого правила ожидайте проблемы при работе в оффлайне или смене типа бэкэнда.
Сортировка
builder.orderBy('age desc, price asc');
По полю мастера:
builder.orderBy('creator.age desc, price asc');
Возвращение первых N записей
builder.top(N);
Пропуск N записей
builder.skip(N);
Подсчет количества результатов
builder.count();
Задание атрибутов для запроса
Проекция и задание атрибутов вычитки (select) - взаимоисключающие вещи, необходимо использовать одно из этого!
builder.select('id,age,name');
Задание проекции для запроса
Проекция и задание атрибутов вычитки(select) - взаимоисключающие вещи, необходимо использовать одно из этого!
builder.selectByProjection('EmployeeTestProjection');
Создание экземпляра запроса на основе заданных данных
builder.build();
Передача экземпляра в query
store.query(modelName, builder.build());
Предикаты
Query.SimplePredicate
Query.SimplePredicate
- класс для простых предикатов для фильтрации поля по значению и указанному оператору.
Конструктор
Конструктор Query.SimplePredicate
принимает 3 параметра: attributePath
- путь атрибута, operator
- оператор, value
- значение.
let predicate = new Query.SimplePredicate('name', Query.FilterOperator.Eq, 'Vasya');
Получение свойств предиката
Получение пути атрибута:
predicate.attributePath
Получение оператора:
predicate.operator
Получение значения фильтрации:
predicate.value
Query.ComplexPredicate
Query.ComplexPredicate
- класс для сложных предикатов, объединяющий несколько предикатов логическими условиями.
Конструктор
Конструктор Query.ComplexPredicate
принимает 2 параметра: condition
- логическое условия для предикатов, ...predicates
- список предикатов для объединения.
let sp1 = new Query.SimplePredicate('name', Query.FilterOperator.Eq, 'Vasya');
let sp2 = new Query.SimplePredicate('surname', Query.FilterOperator.Eq, 'Ivanov');
let cp1 = new Query.ComplexPredicate(Query.Condition.Or, sp1, sp2);
Другой вариант:
let p1 = new Query.SimplePredicate('name', Query.FilterOperator.Eq, 'Vasya');
let p2 = new Query.SimplePredicate('surname', Query.FilterOperator.Eq, 'Ivanov');
let result = p1.or(p2);
Получение свойств предиката
Получение логического условия:
complexPredicate.condition
Получение списка предикатов:
complexPredicate.predicates
Добавление к существующему сложному предикату новых.
Возьмем cp1 из примера для конструктора. Добавление через and:
let sp3 = new Query.SimplePredicate('nationality', Query.FilterOperator.Eq, 'Russian');
let result = cp1.and(sp3);
Добавление через or:
let sp3 = new Query.SimplePredicate('nationality', Query.FilterOperator.Eq, 'Russian');
let result = cp1.or(sp3);
Query.StringPredicate
Query.StringPredicate
- класс для построения фильтров по строковым полям.
Конструктор
Конструктор Query.StringPredicate
принимает единственный параметр: attributePath
- путь атрибута предиката.
Поиск по подстроке
Добавление значения, которое заданный в конструкторе атрибут должен содержать:
let sp1 = new Query.StringPredicate('country').contains('i');
Добавление значения, которое атрибут мастера должен содержать:
let sp1 = new Query.StringPredicate('country.name').contains('i');
Получение свойств предиката
Получение пути атрибута:
predicate.attributePath
Получение значения, которое должно содержаться в атрибуте:
predicate.containsValue
Query.DetailPredicate
Query.DetailPredicate
- класс для построения фильтров по детейлам.
Конструктор
Конструктор Query.DetailPredicate
принимает единственный параметр - наименование детейла.
let dp = new Query.DetailPredicate('detailName')
Добавление простого предиката для всех детейлов
dp.all(new Query.SimplePredicate('name', Query.FilterOperator.Eq, 'Tag1'));
или
let p = new Query.DetailPredicate('detailName').all('field', Query.FilterOperator.Eq, 'Value');
Для поля мастера
dp.all(new Query.SimplePredicate('creator.name', Query.FilterOperator.Eq, 'X'));
Добавление простого предиката для любого детейла
dp.any(new Query.SimplePredicate('name', Query.FilterOperator.Eq, 'Tag1'));
или
let p = new Query.DetailPredicate('detailName').any('field', Query.FilterOperator.Eq, 'Value');
Для поля мастера
dp.any(new Query.SimplePredicate('creator.name', Query.FilterOperator.Eq, 'X'));
Добавление сложного предиката для всех детейлов
let sp1 = new Query.SimplePredicate('name', Query.FilterOperator.Eq, 'Tag1');
let sp2 = new Query.SimplePredicate('name', Query.FilterOperator.Eq, 'Tag3');
let cp1 = new Query.ComplexPredicate(Query.Condition.Or, sp1, sp2);
let dp = new Query.DetailPredicate('tags').all(cp1);
Для поля мастера
let sp1 = new Query.SimplePredicate('creator.name', Query.FilterOperator.Eq, 'X');
let sp2 = new Query.SimplePredicate('creator.name', Query.FilterOperator.Eq, 'Z');
let cp1 = new Query.ComplexPredicate(Query.Condition.Or, sp1, sp2);
let dp = new Query.DetailPredicate('tags').all(cp1);
Добавление сложного предиката для любого детейла
let sp1 = new Query.SimplePredicate('name', Query.FilterOperator.Eq, 'Tag1');
let sp2 = new Query.SimplePredicate('name', Query.FilterOperator.Eq, 'Tag2');
let cp1 = new Query.ComplexPredicate(Query.Condition.Or, sp1, sp2);
let dp = new Query.DetailPredicate('tags').any(cp1);
Для поля мастера
let sp1 = new Query.SimplePredicate('creator.name', Query.FilterOperator.Eq, 'X');
let sp2 = new Query.SimplePredicate('creator.name', Query.FilterOperator.Eq, 'Y');
let cp1 = new Query.ComplexPredicate(Query.Condition.Or, sp1, sp2);
let dp = new Query.DetailPredicate('tags').any(cp1);
Query.DatePredicate
Query.DatePredicate
- класс для предикатов для фильтрации поля с типом дата по значению и указанному оператору.
Конструктор
Конструктор Query.DatePredicate
принимает 4 параметра: attributePath
- путь атрибута, operator
- оператор, value
- значение и timeless
- флаг указывающий нужно ли учитывать время при сравнении дат (если true, то время не учитывается).
let predicate = new Query.DatePredicate('birthday', Query.FilterOperator.Eq, '2018-02-06T11:00:00.000Z');
let predicate = new Query.DatePredicate('birthday', Query.FilterOperator.Eq, '2018-02-06', true);
Получение свойств предиката
Получение пути атрибута:
predicate.attributePath
Получение оператора:
predicate.operator
Получение значения фильтрации:
predicate.value
Получение флага учета времени:
predicate.timeless
Query.NotPredicate
Query.NotPredicate
– класс для инверсии вложенного предиката.
Конструктор
Конструктор Query.NotPredicate
принимает единственный параметр – другой предикат.
let np = new Query.NotPredicate(new Query.SimplePredicate('creator.name', Query.FilterOperator.Eq, 'X'));
Получение свойств предиката
Получение вложенного предиката:
let innerPredicate = np.predicate;
Query.IsOfPredicate
Конструктор
Конструктор Query.IsOfPredicate
с двумя параметрами принимает строку с выражением, указывающим на свойство модели, и строку с именем модели.
let predicate = new Query.IsOFPredicate('manager', 'employee');
Конструктор Query.IsOfPredicate
с одним параметром принимает строку с именем модели.
let predicate = new Query.IsOFPredicate('customer');
Есть метод упрощающий работу с этим предикатом.
let predicate = new Query.IsOFPredicate('man');
let builder = new Query.Builder(store, 'creator').where(predicate);
Равнозначное выражение без использования предиката.
let builder = new Query.Builder(store, 'creator').isOf('man');
Query.InPredicate
Query.InPredicate
- класс для создания фильтра в запросе по значению атрибута, входящего в заданный список значени.
Конструктор
Конструктор Query.InPredicate
принимает 2 параметра: attributePath
- путь атрибута, valueArray
- массив значений, для проверки вхождения в него значения атрибута.
let predicate = new Query.InPredicate('name', ['Vasya', 'Petia', 'Ivan']);
Получение свойств предиката
Получение пути атрибута:
predicate.attributePath
Получение массива значений:
predicate.valueArray
Логические операторы для сложных предикатов
Or
Query.Condition.Or
let cp1 = new Query.ComplexPredicate(Query.Condition.Or, sp1, sp2);
And
Query.Condition.And
let cp1 = new Query.ComplexPredicate(Query.Condition.And, sp1, sp2);
Операторы для фильтрации данных для простых предикатов
Равенство
Query.FilterOperator.Eq
let sp1 = new Query.SimplePredicate('name', Query.FilterOperator.Eq, 'Tag1');
Неравенство
Query.FilterOperator.Neq
let sp1 = new Query.SimplePredicate('name', Query.FilterOperator.Neq, 'Tag1');
Больше
Query.FilterOperator.Ge
let builder = new Query.QueryBuilder(store, modelName).where('age', Query.FilterOperator.Ge, 10);
Больше или равно
Query.FilterOperator.Geq
let builder = new Query.QueryBuilder(store, modelName).where('age', Query.FilterOperator.Geq, 11);
Меньше
Query.FilterOperator.Le
let builder = new Query.QueryBuilder(store, modelName).where('age', Query.FilterOperator.Le, 12);
Меньше или равно
Query.FilterOperator.Leq
let builder = new Query.QueryBuilder(store, modelName).where('age', Query.FilterOperator.Leq, 11);
Создание запроса для фильтрации перечислений
По названию и типу перечисления берется name
и пишется в предикат:
let enumValues = Ember.getOwner(this).lookup('enum:' + filter.type);
let pattern = '';
for (let key in enumValues) {
if (enumValues[key] === filter.pattern) {
pattern = key;
break;
}
}
switch (filter.condition) {
case 'Равно':
return new SimplePredicate(filter.name, FilterOperator.Eq, pattern);
case 'Не равно':
return new SimplePredicate(filter.name, FilterOperator.Neq, pattern);
// по умолчанию Равно
default:
return new SimplePredicate(filter.name, FilterOperator.Eq, pattern);
}
Пример комплексного запроса
let builder = new Query.QueryBuilder(store)
.from('customer')
.select('id,firstName,lastName,age')
.where('firstName', Query.FilterOperator.Eq, 'Vasya')
.top(50)
.skip(100)
.count();