Hi Serdar,
I forgot one more optimization: You can take advantage of maps in XQuery 3.1 and cache repeatedly accessed values in advance:
let $Conts := map:merge(//Cont/map { @id/string(): . }) let $PlCts := //PlCt[environment = 'AIR']/@id for $PlGeTy in //PlGeTy[isOfPlCt/@href = $PlCts] for $PlSpTy in //PlSpTy[isOfPlGeTy/@href = $PlGeTy/@id] for $Cont in $Conts($PlSpTy/isOfCont/@href) return <done>{ $PlGeTy, $PlSpTy, $Cont }</done>
If you are wondering what's going on in the first line of code.. Here is a more verbose writing:
map:merge( for $Cont in //Cont return map { $Cont/@id/string(): $Cont } )
You can even take this further and create maps for all accessed ids in advance, as shown in the query below. However, please note that...
* this may take a lot of memory if your document contains a large number of entries * it may get slower than the original query if you only a few of the cached entries * as you see below, you'll have to group entries if there is more than one entry with the same key.
Maps in XQuery are a powerfull feature. It may take some time to get to know them, but it's really worth the trouble..
Have fun, Christian
let $Conts := map:merge(//Cont/map { @id/string(): . }) let $PlGeTys := map:merge( for $value in //PlGeTy group by $key := $value/isOfPlCt/@href/string() return map { $key: $value } ) let $PlSpTys := map:merge( for $value in //PlSpTy group by $key := $value/isOfPlGeTy/@href/string() return map { $key: $value } )
for $PlCts in //PlCt[environment = 'AIR']/@id for $PlGeTy in $PlGeTys($PlCts) for $PlSpTy in $PlSpTys($PlGeTy/@id) for $Cont in $Conts($PlSpTy/isOfCont/@href) return <done>{ $PlGeTy, $PlSpTy, $Cont }</done>