I've a use case where user can type in text and the system searches for matching Invoices. The typed in text can match on multiple fields on both Invoice but also Invoice Lines.
A user has only access to a subset of all invoices based on roles. But this could be a list of thousands of invoices.
The searching is done by a straight-forward like search in combination with wildcards. (Queries are written in hql)
in showing result we want to limit it to 50, as to not select/process thousands of entries depending on what the user searched. However, with the way I join this limit can't be enforced by the database.
We used to have something like (pseudo code)
select * from tbl_invoice
join tbl_useraccess .... :userid //a few joins happen here to limit to invoices
//where the user has access to
where number like :input
or name like :input
or id in (select id from InvoiceLine where reference like :input)
limit top 50
This has very bad performance as the search is done on each invoice line, instead of just the ones where you have access to, but does always give the correct 50 lines.
I've changed this to
select * from tbl_invoice invoice
join tbl_useraccess .... :userid
join tbl_invoiceline line on invoice.id = line.invoice_id
where number like :input
or name like :input
or line.reference like :input
limit top 50
Performance is way better (previous statement would just timeout) but the limit doesn't work because there could multiple lines for one invoice.
We could retrieve all results from the database, map it to the java objects and do the max 50 results in Java but I'm afraid this could blow-up our memory if a user retrieves thousands-millions of records.
So in conclusion, I'm looking for a better way to retrieve a fixed list of results but also be able to search in a linked 1-n entity