On 18/08/16 06:42, Niels Andersen wrote:
Dear Apache Jena users group,
We are using Apache Jena with a combination of a persistent TDB database and an
in memory inference model. Our implementation is based on the Jena API.
We are using Jena rules to drive the reasoner. We are using
GenericRuleReasoner.FORWARD_RETE for performance reasons.
Given the following example data in ttl format:
ex:Invoice_1
rdf:type ex:Invoice;
ex:customer ex:Customer_1;
.
ex:InvoiceItem_1
rdf:type ex:InvoiceItem;
ex:invoice ex:Invoice_1;
ex:invoiceItem_Product ex:Product_1;
ex:invoiceItem_Amount "30.0"^^xsd:decimal;
.
ex:InvoiceItem_2
rdf:type ex:InvoiceItem;
ex:invoice ex:Invoice_1;
ex:invoiceItem_Product ex:Product_1;
ex:invoiceItem_Amount "30.0"^^xsd:decimal;
.
ex:InvoiceItem_3
rdf:type ex:InvoiceItem;
ex:invoice ex:Invoice_1;
ex:invoiceItem_Product ex:Product_4;
ex:invoiceItem_Amount "105.0"^^xsd:decimal;
.
The example above shows one invoice (ex:Invoice_1) with three invoice line
items. Each invoice line item has an associated amount.
I want to set the amount of the invoice to the sum of the amounts of the line
items. My preferred approach would be to use Jena rules to do this, but I
cannot see how that is possible. The reason that I would prefer to use a rule
over a SPARQL construct is that the rule has to be called iteratively many
times (our actual implementation is a lot more demanding than the example
above).
Looking at the Jena Builtin functions
(https://jena.apache.org/documentation/inference/#builtin-primitives ) I see
that there is a sum function, but this is sum(?a, ?b, ?c) that results in ?c =
?a + ?b, not the sum of all values that meet a certain criteria (aggregate
function).
Is it possible to create a rule like this (sumByGroup is a made up function
with the first argument being the group, the second being what should be
summed, and the third being the return variable):
[InvoiceSumAmountRule:
(?Invoice rdf:type ex:Invoice), (?InvoiceItem ex:invoice ?Invoice),
(?InvoiceItem ex:invoiceItem_Amount ?Amount), sumByGroup(?Invoice, ?Amount,
?SumAmount)
->
(?Invoice ex:invoice_Amount ?SumAmount)
]
Any suggestions about how to solve this would be appreciated. It does not have
to be done with rules (even though that is preferred), it could also be done in
Java (Jena API) or using SPARQL / ARQ.
Short answer on rules is don't use them for this. Something like "sum of
all invoice items present" is a non-monotonic operation and JenaRules
are really not suited to this. It is *possible* to do by JenaRules but
you have to keep track of whether all the items are in the sum yet,
remove partial sums and effectively create a mini iterative loop using
rules - this ends up being really clunky, slow and hard to maintain.
It's perfectly possible to have rule systems which handle this sort of
thing well but JenaRules isn't one of them.
Not sure I understand what the problem is with using SPARQL or the API.
Dave