No easy suggestions, but I have a couple.

If this is a common query and needs to be very efficient, then I would create a 
node that represents the fact that elem/@attr1 eq elem/@attr2. Then you could 
use something like:

    cts:element-attribute-value-query(xs:QName('elem'), 
xs:QName('attrs-equal'), '1').

If you prefer fewer XML changes and more database round-trips, you could put a 
range index on elem/@attr1 (or elem/@attr2, but let's use attr1 for now). Then 
you could write:

    cts:element-attribute-value-query(
      xs:QName('elem'), xs:QName('attr2'),
      cts:element-attribute-values(
        xs:QName('elem'), xs:QName('attr1')))

You could speed that query up even further by configuring a range index on both 
element-attribute pairs, and then using cts:element-attribute-range-query with 
'=' instead of cts:element-attribute-value-query. But the 'attrs-equal' 
approach will still outperform it most of the time, and won't use as much 
memory or disk space.

Why is any of this necessary? Because the cts:query constructors are designed 
to be searchable - that is, to allow efficient index lookups. But there is no 
index that would answer your question directly. There is an index entry for 
every value of //elem/@attr1[. eq VALUE] and for //elem/@attr2[. eq VALUE] but 
no index entry that says //elem/@attr1[. eq attr2]. So the most straightforward 
way to resolve the XPath is to retrieve every match for //elem[@attr1][@attr2] 
and then filter in memory to check the @attr1 eq @attr2 portion.

When xdmp:plan says "Path is fully searchable", I think it's only talking about 
any node-name and node-type step(s), not any predicates. When I call it on your 
XPath expression, it shows only one constraint, and I get exactly the same plan 
if I simply drop the predicate. So I think it's really only searching on 
//elem, and ignoring both attributes until the filtering phase (that's with 
5.0-2).

Compare these plans:

xdmp:plan(//elem[@att1 = @att2]),
xdmp:plan(//elem),
xdmp:plan(//elem[@attr1])
=>
<qry:query-plan xmlns:qry="http://marklogic.com/cts/query";>
  <qry:info-trace>xdmp:eval("xdmp:plan(//elem[@att1 = 
@att2]),&amp;#13;&amp;#10;xdmp:plan(//elem),&amp;#1...", (), &lt;options 
xmlns="xdmp:eval"&gt;&lt;database&gt;18400529833056734238&lt;/database&gt;&lt;root&gt;/Users/mblakele/S...&lt;/options&gt;)</qry:info-trace>
  <qry:info-trace>Analyzing path: fn:collection()/descendant::elem[@att1 = 
@att2]</qry:info-trace>
  <qry:info-trace>Step 1 is searchable: fn:collection()</qry:info-trace>
  <qry:info-trace>Step 2 is searchable: descendant::elem[@att1 = 
@att2]</qry:info-trace>
  <qry:info-trace>Path is fully searchable.</qry:info-trace>
  <qry:info-trace>Gathering constraints.</qry:info-trace>
  <qry:info-trace>Executing search.</qry:info-trace>
  <qry:final-plan>
    <qry:and-query>
      <qry:term-query weight="0">
        <qry:key>7128167059298760147</qry:key>
      </qry:term-query>
    </qry:and-query>
  </qry:final-plan>
  <qry:info-trace>Selected 0 fragments</qry:info-trace>
  <qry:result estimate="0"/>
</qry:query-plan>
<qry:query-plan xmlns:qry="http://marklogic.com/cts/query";>
  <qry:info-trace>xdmp:eval("xdmp:plan(//elem[@att1 = 
@att2]),&amp;#13;&amp;#10;xdmp:plan(//elem),&amp;#1...", (), &lt;options 
xmlns="xdmp:eval"&gt;&lt;database&gt;18400529833056734238&lt;/database&gt;&lt;root&gt;/Users/mblakele/S...&lt;/options&gt;)</qry:info-trace>
  <qry:info-trace>Analyzing path: 
fn:collection()/descendant::elem</qry:info-trace>
  <qry:info-trace>Step 1 is searchable: fn:collection()</qry:info-trace>
  <qry:info-trace>Step 2 is searchable: descendant::elem</qry:info-trace>
  <qry:info-trace>Path is fully searchable.</qry:info-trace>
  <qry:info-trace>Gathering constraints.</qry:info-trace>
  <qry:info-trace>Executing search.</qry:info-trace>
  <qry:final-plan>
    <qry:and-query>
      <qry:term-query weight="0">
        <qry:key>7128167059298760147</qry:key>
      </qry:term-query>
    </qry:and-query>
  </qry:final-plan>
  <qry:info-trace>Selected 0 fragments</qry:info-trace>
  <qry:result estimate="0"/>
</qry:query-plan>
<qry:query-plan xmlns:qry="http://marklogic.com/cts/query";>
  <qry:info-trace>xdmp:eval("xdmp:plan(//elem[@att1 = 
@att2]),&amp;#13;&amp;#10;xdmp:plan(//elem),&amp;#1...", (), &lt;options 
xmlns="xdmp:eval"&gt;&lt;database&gt;18400529833056734238&lt;/database&gt;&lt;root&gt;/Users/mblakele/S...&lt;/options&gt;)</qry:info-trace>
  <qry:info-trace>Analyzing path: 
fn:collection()/descendant::elem[@attr1]</qry:info-trace>
  <qry:info-trace>Step 1 is searchable: fn:collection()</qry:info-trace>
  <qry:info-trace>Step 2 is searchable: 
descendant::elem[@attr1]</qry:info-trace>
  <qry:info-trace>Path is fully searchable.</qry:info-trace>
  <qry:info-trace>Gathering constraints.</qry:info-trace>
  <qry:info-trace>Step 2 predicate 1 contributed 1 constraint: 
@attr1</qry:info-trace>
  <qry:partial-plan>
    <qry:term-query weight="0">
      <qry:key>11100480210632785569</qry:key>
    </qry:term-query>
  </qry:partial-plan>
  <qry:info-trace>Step 2 predicate 1 contributed 1 constraint: 
@attr1</qry:info-trace>
  <qry:partial-plan>
    <qry:term-query weight="0">
      <qry:key>11100480210632785569</qry:key>
    </qry:term-query>
  </qry:partial-plan>
  <qry:info-trace>Executing search.</qry:info-trace>
  <qry:final-plan>
    <qry:and-query>
      <qry:or-query>
        <qry:element-query>
          <qry:key>7128167059298760147</qry:key>
          <qry:and-query>
            <qry:term-query weight="0">
              <qry:key>11100480210632785569</qry:key>
            </qry:term-query>
          </qry:and-query>
        </qry:element-query>
        <qry:and-query>
          <qry:term-query weight="0">
            <qry:key>11397336598217694489</qry:key>
          </qry:term-query>
          <qry:term-query weight="0">
            <qry:key>7128167059298760147</qry:key>
          </qry:term-query>
          <qry:term-query weight="0">
            <qry:key>11100480210632785569</qry:key>
          </qry:term-query>
        </qry:and-query>
      </qry:or-query>
    </qry:and-query>
  </qry:final-plan>
  <qry:info-trace>Selected 0 fragments</qry:info-trace>
  <qry:result estimate="0"/>
</qry:query-plan>

If attr1 or attr2 aren't ubiquitous, then I think the efficient way to write 
the XPath might be this odd-looking expression:

    //elem[@attr1][@attr2][@att1 = @att2]

-- Mike

On 12 Feb 2012, at 01:16 , Geert Josten wrote:

> I am trying to isolate some specific element with two attributes who's
> values are equal. I know I can use an expression like doc()//elem[@att1 =
> @att2], which is even fully searchable according to xdmp:plan, but I'd
> prefer a cts:query, which I could pass into cts:element-attribute-values.
> I need unique values, and I am trying to prevent using distinct-values on
> the above XPath expression..
> 
> Any suggestions?
> 
> Kind regards,
> Geert
> 
> drs. G.P.H. (Geert) Josten
> Senior Developer
> 
> 
> 
> Dayon B.V.
> Delftechpark 37b
> 2628 XJ Delft
> 
> T +31 (0)88 26 82 570
> 
> [email protected]
> www.dayon.nl
> 
> De informatie - verzonden in of met dit e-mailbericht - is afkomstig van
> Dayon BV en is uitsluitend bestemd voor de geadresseerde. Indien u dit
> bericht onbedoeld hebt ontvangen, verzoeken wij u het te verwijderen. Aan
> dit bericht kunnen geen rechten worden ontleend.
> _______________________________________________
> General mailing list
> [email protected]
> http://developer.marklogic.com/mailman/listinfo/general
> 

_______________________________________________
General mailing list
[email protected]
http://developer.marklogic.com/mailman/listinfo/general

Reply via email to