[xquery-talk] Using Union/Intersect to Combine Two User-Defined Function Results

Jonathan Robie jonathan.robie at redhat.com
Tue Mar 25 16:11:04 PST 2008


Wei, Alice J. wrote:
> Hi, XQueriers:
>
>    I am working on a search engine and right now I am making attempts to combine two sets of results using union, intersect or except operators. Here is a snippet:
>
>  if (($search ne "") and ($search2 eq "address") and ($search3 eq "address") and ($search5  ne "") and ($search7 eq "and") and ($search6 eq "") and ($search4 eq  "head") and ($search8 eq "and"))
> then <div><p>This is Your Term of Search : {$search} in &#60;{$search2}&#62; {$search7} {$search5} in &#60;{$search3}&#62;</p>
> {local:count-distinct-values(collection("my")//ad//address[contains(., $search)])} intersect {local:count-distinct-values(collection("my")//ad//address[contains(., $search5)]) }
> </div>
> else <p>I don't know what you want.</p>
>
> If I tried using another curly brace to surround the above statements and have my function call as in: {local:count-distinct-values(collection("my")//ad//address[contains(., $search)]) intersect local:count-distinct-values(collection("my")//ad//address[contains(., $search5)]) }
>
> This bring me no output and no errors.
>   

Are you sure that there is a non-empty intersection for the two sets? 
Remember that intersection of nodes is based on identity, not value, so 
even if the values are the same two nodes can be considered separate.

Try doing a count() on each side of the intersect, then change the world 
"intersect" to "union" and do a count for the entire union. If the count 
of the union adds up to the count of the two sides, there is no 
intersection, which is why you get no results.

Are you using element constructors to contain the results of your 
searches? Remember that newly constructed nodes will always have 
distinct identity. For instance, in the following example, $a intersect 
<a/> is always an empty sequence:

let $a := <a/>,
$b := <b/>,
$c := <c/>
return
<foo>{ $a intersect <a/> }</foo>


> However, if I use the {local:count-distinct-values(collection("my")//ad//address[contains(., $search)])} intersect {local:count-distinct-values(collection("my")//ad//address[contains(., $search5)]) }
>
> it gives me the first part of the query, with the actual word, intersect in between, and followed by the second portion of the query after the word "intersect."
>   

Is this the entire query, or is this embedded in an element constructor? 
If it's in an element constructor, that's completely expected. Compare 
it to the following queries:

Query:

<foo>{ 1 + 2 } intersect { 3 + 4 }</foo>

Output:

<foo>3 intersect 7</foo>

Query:

let $a := <a/>,
$b := <b/>,
$c := <c/>
return
<foo>{ ($a union $b) intersect ($b union $c) }</foo>

Output:

<foo><b/></foo>

Jonathan


More information about the talk mailing list