OrientDB supports fetching strategies by using the Fetch Plans. Fetch Plans are used to customize how OrientDB must load linked records.
Example:
Invoice
3:100
|
| customer
+---------> Customer
| 5:233
| address city country
+---------> Address---------> City ---------> Country
| 10:1 11:2 12:3
|
| orders
+--------->* [OrderItem OrderItem OrderItem]
[ 8:12 8:19 8:23 ]
By default OrientDB loads all the linked records in lazy way. So in this example the linked "customer", "city" and "orders" fields are not loaded until are traversed. If you need the entire tree it could be slow the lazy loading of every single linked record. In this case it would need 7 different loads. If the database is open on a remote server they are 7 different network calls.
This is the reason why OrientDB supports custom fetching strategies using the Fetch Plans. The aim of fetch plans is to pre-load connected records in one shot.
Where use fetch-plans?
When a client executes a query (or load directly one single record) setting a fetch plan with level different to 0, then the server traverses all the records of the returning result set and sends them to the client in the same call.
The client avoid to connect directly them to the record by using always the lazy collections (i.e.: OLazyRecordList). Instead, loads all the connected records into the local client. In this ways the collections remain lazy but when you're accessing to the content, the record is early loaded from the local cache avoiding other connections.
The fetch plan comes in form of a String and can be used at run-time on:
The syntax is:
[[levels]]<fieldPath>:<depth-level>*
Where:
[0]
to apply only at first level[0-3]
form 0 to 3th level. Ranges can be also partial, like [-3]
means 0-3 and [3-]
means form 3rd to infinite*
. Example [*]
to apply at any level
for "any" field. The wildcard can be also at the end of the path to specify all the paths that starts for a nameTo express multiple rules separate them by spaces.
Examples with the record tree above:
"*:-1"
: fetches the entire tree recursively"*:-1 orders:0"
: fetches all the records recursively but the "orders" field in root class. Note that in "orders" field will be loaded only its direct content (only records 8:12,8:19,8:23, none of other records inside them will be loaded)."*:0 address.city.country:0"
: fetches only not-document fields in the root class and address.city.country field (records 10:1,11:2,12:3)."[*]in_*:-2 out_*:-2"
: returns all the properties, but edges (at any level)OrientDB handles circular dependencies to avoid any loop while fetches linking records.
List<ODocument> resultset = database.query(new OSQLSynchQuery<ODocument>("select * from Profile").setFetchPlan("*:-1"));
Export an invoice and its customer:
invoice.toJSON("fetchPlan:customer:1");
Export an invoice, its customer and orders:
invoice.toJSON("fetchPlan:customer:1 orders:2");
Export an invoice and all the connected records up to 3rd level of depth:
invoice.toJSON("fetchPlan:*:3");
From SQL:
select @this.toJSON('fetchPlan:out_Friend:4') from #10:20
Export path in outgoing direction by removing all the incoming edges by using wildcards (Since 2.0):
select @this.toJSON('fetchPlan:in_*:-2') from #10:20
NOTES::
for (Account a : database.browseClass(Account.class).setFetchPlan("*:0 addresses:-1")) {
System.out.println( a.getName() );
}
NOTE: fetching Object will mean their presence inside your domain entities. So if you load an object using fetchplan *:0
all LINK type references won't be loaded.