I have two lists of elements which I use to query a third type of elements (in eXist DB). But since I only want those results that are found by both queries (i.e. satisfy two sets of initial parameters) I do an intersection of those two sub-results:
let $aList1 := for $elementB in $elementListB return //ElementA[ft:query(@referenceB, $elementB/@id)]
let $aList2 := for $elementC in $elementListC return //ElementA[ft:query(@referenceC, $elementC/@id)]
let $results := $aList1 intersect $aList2
The thing is, there is a function i need to call on each element in the starting lists to get some additional info. Normally I would do something like this:
let $aList1 := for $elementB in $elementListB
let $additionalInfo := additionalInfoFunction($elementB)
return
<wrapper>
<additionalInfo>{$additionalInfo}</additionalInfo>
{
//ElementA[ft:query(@referenceB, $elementB/@id)]
}
</wrapper>
However, if I do this I will not be able to perform intersection of $aList1 and $aList2 since intersection works with references not values.
I thought of calling the additionalInfoFunction after the intersection like this:
return for $result in $results
let $elementB := $elementListB[@id = $result/@referenceB]
let $additionalInfo := additionalInfoFunction($elementB)
return
<wrapper>
<additionalInfo>{$additionalInfo}</additionalInfo>
{
BLA BLA
}
</wrapper>
But the problem here is that while $elementListB and $elementListC only contain a few elements, $results can contain hundreds which is a problem since additionalInfoFunction is relatively expensive.
Is there some clever workaround here which I just can’t see?
XQuery is a functional language with immutable variables and thus without side-effects.
Whether a function or operator like
intersectswill return references or not is only relevant for the implementation (references could be faster), but as all values are immutable, this can never be a problem to you.The actual problem is related, but not similar;
intersectsdoes not do a deep-equal but only looks at some internal “node id” (or reference if you want). Creating two elements – though containing the same contents – will creating different nodes, sointersectwill return no results.You will have to build your own intersects, which isn’t too difficult:
This will return all elements from
$afor which there is some element in$bwhich deep-equals the one from$a.