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

Wei, Alice J. ajwei at indiana.edu
Tue Mar 25 16:30:45 PST 2008

From: Jonathan Robie [jonathan.robie at redhat.com]
Sent: Tuesday, March 25, 2008 4:11 PM
To: Wei, Alice J.
Cc: talk at x-query.com
Subject: Re: [xquery-talk] Using Union/Intersect to Combine Two User-Defined Function Results

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.

This is the part I have to check for my count(), which each of them has a different xpath syntax to check:

let $count := count(collection("my")//ad/head[contains(upper-case(.),$search)])

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/>
<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:


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


<foo>3 intersect 7</foo>


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



To answer your question, each of my local:searchresult functions as something like local:searchresult((collection("my")//ad/p[contains(upper-case(.),$search)])
  is a self efficient XML document with several nodes within it. Each of the output is something like:

<head type="main">
<emph rend="red">FREE</emph>
        <p>Thousands of users actual decals for a 2 deuce coupe! You'll receive free
                        over 100 different. use on your bike, model car, van, plane, or on glass
                        painted surfaces, metal, plastic, etc. </p>     </ad>

What I am trying to do here is to combine both of the result sets into one.
Therefore, if a user intends to see the output of a search term and another term, he would only see the combined result.
Would you say this is possible?

Thanks for your help.
Alice Wei
MIS 2008
School of Library and Information Science
Indiana University Bloomington
ajwei at indiana.edu

More information about the talk mailing list