I'm optimising a query attempting to use a filter with 'Terrasoft.ComparisonType.EXISTS', I'm guessing at the syntax and it isn't working.  If anyone could point out where I'm going wrong here:

...
const subFilter = Terrasoft.createFilterGroup();
subFilter.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrRefundItem", true));
const esqSecondFilter = Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EXISTS, subFilter);
esq.filters.add("esqSecondFilter", esqSecondFilter);
...

Thanks,

 

Like 0

Like

8 comments

Hello Gareth,

 

Terrasoft.ComparisonType.EXISTS is not used in the client-side system logic anymore since it was replaced with the createExistsFilter function. So you need to use it instead of EXISTS comparison type.

 

Best regards,

Oscar

Oscar Dylan,

I have tried the following but it is returning more than one record:

const caseId = this.get("MasterRecordId");
const esq = this.Ext.create(Terrasoft.EntitySchemaQuery, {
	rootSchemaName: "UsrItemInOrder"
});
esq.addAggregationSchemaColumn("Id", Terrasoft.AggregationType.COUNT, "RefundCount", Terrasoft.AggregationEvalType.ALL);
const esqFirstFilter = esq.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrCase", caseId);
esq.filters.addItem(esqFirstFilter);
var subFilter = Terrasoft.createFilterGroup();
subFilter.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrRefundItem", true));
const esqSecondFilter = Terrasoft.createExistsFilter("Id", subFilter);
...

I am not filtering with a subquery here, just on the one table.

Gareth Osler,

Hi Gareth. Here is a sample of how to get a count (this gets a count of all accounts with a type of "Customer", however, to just get a count of the entire table you'd just omit the filter):

var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
    rootSchemaName: "Account"
});
esq.addAggregationSchemaColumn("Id", Terrasoft.AggregationType.COUNT, "AccountCount");
esq.filters.add(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "Type.Name", "Customer"));
esq.getEntityCollection(function(result) {
    console.log("Total customers", result.collection.first().get("AccountCount"));
});

With an exists sub-filter like in your code, it would look like this:

// get a count of all accounts with a "UsrClientSystem" record that has a system type of "Creatio"
var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
    rootSchemaName: "Account"
});
esq.addAggregationSchemaColumn("Id", Terrasoft.AggregationType.COUNT, "AccountCount");
 
var subFilter = Terrasoft.createFilterGroup();
subFilter.addItem(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrSystemType.Name", "Creatio"));
esq.filters.addItem(Terrasoft.createExistsFilter("[UsrClientSystem:UsrAccount].Id", subFilter));
 
esq.getEntityCollection(function(result) {
    console.log("Total accounts with Creatio system", result.collection.first().get("AccountCount"));
}, this);

Ryan

Ryan Farley, Thank you for the reply.  I am querying with an exists filter on the same table as the esq query, the esq query is on table UsrItemInOerder, for an exist filter of there exists a record with a UsrRefundItem column value of true.  What would the column path be for a createExistsFilter() call in that situation?

Gareth Osler,

I'm not 100% sure I follow. So you want to know if there's a UsrItemInOrder record for the parent Order that has a value of true for the UsrRefundItem column? If that's the case, you can just simplify the query (no need for the exists sub filter):

var esq = this.Ext.create("Terrasoft.EntitySchemaQuery", {
    rootSchemaName: "UsrItemInOrder"
});
// get a count of items with a refund
esq.addAggregationSchemaColumn("Id", Terrasoft.AggregationType.COUNT, "RefundCount");
// for all UsrItemInOrder rows for the parent Order
esq.filters.add(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "Order", this.get("MasterRecordId"));
// add filter for refund items only
esq.filters.add(Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "UsrRefundItem", true);
// get result, this will return 1 row with a count of refund items in RefundCount column
esq.getEntityCollection(function(result) {
    var hasRefunds = (result.collection.first().get("RefundCount") > 0);
});

Ryan

Ryan Farley,

That is essentially what I have done.  But could that query be optimized with an exists query, it is being run on a database with circa 1.5 million records.

 

Gareth Osler,

What I was trying to do is illustrated in SQL terms in this stackexchange question,

SELECT TOP (1) id 
  FROM dbo.table
  WHERE price IS NULL
    AND category = 'hardware';

which I am arriving at the conclusion is not possible with a Creatio ESQ query.  The solution counting the records matching the case Id and 'UsrRefundItem'

flag true conditions is probably the fastest otherwise.

Gareth Osler,

The only way to do a "top" or "limit" that I know of via ESQ is like this:

var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
	rootSchemaName: "UsrEntity"
});
// get only first row in results
esq.rowCount = 1;
esq.addColumn("Id");
// add any filters
esq.getEntityCollection(function(response) {
	// only one row returned
}, this);

To be honest, I've never ran profiler to see if rowCount=X actually does translate to TOP X or LIMIT X, but I assume it does. However, I think the previous method of getting the count would be a more efficient way. The ESQ I posted earlier is the equivalent of:

select count(Id) as RefundCount from UsrItemInOrder where OrderId = 'SOMEID' and UsrRefundItem = 1

Ryan

Show all comments