One other idea you might want to try (not sure if it will help or not but would 
be easy enough to experiment with).

Assuming you have a Lexicon URI, you could use a cts:uris query to identify 
those documents containing the chapter, subchapter, or section with the 
attribute value.  You could then iterate over these URIs with a doc($uri) and a 
simple XPath expression to retrieve only the chapter, subchapter, section with 
the attribute value.  If you don't know the QNames in advance, you could use 
xdmp:unpath.  Logically, I believe this is what Mike is suggesting below ... 
just doing it a bit different.  Like I said, don't know if it would be 
slower/faster.

Darin.



________________________________
From: Michael Blakeley <[email protected]>
To: General MarkLogic Developer Discussion <[email protected]>
Sent: Wednesday, July 27, 2011 7:59 PM
Subject: Re: [MarkLogic Dev General] xpath to cts query question

You might get a little faster by using doc() for the cts:search arg1, and 
relying on XPath to walk the trees. And since you are doing that, don't bother 
with filtering in cts:search.

let $qnames :=
  for $i in ("chapter", "subchapter", "section")
  return xs:QName($i)
return
  cts:search(
    doc(),
    cts:and-query(
      (cts:directory-query($coll, "infinity"),
       cts:element-attribute-value-query(
         $qnames, xs:QName("enum"), $enum))),
    "unfiltered")//(chapter | subchapter | section)[@enum eq $enum]

I don't know if that will be faster or slower, but it's worth a try.

Another variation is to go back to the XPath, and enumerate all the possible 
path expressions.

  /(a[@v eq $v] | a/b[@v eq $v] | a/b/c[@v eq $v])

-- Mike

On 27 Jul 2011, at 16:50 , Will Thompson wrote:

> This is the best I could come up with:
> 
> let $qnames := for $i in ("chapter","subchapter","section") return 
> xs:QName($i)
> return cts:search(//(chapter|subchapter|section),
>            cts:and-query((
>                cts:directory-query($coll,"infinity"),
>                cts:element-attribute-value-query($qnames, 
>xs:QName("enum"),$enum))))[@enum eq $enum]
> 
> This is still about twice as fast as the xpath, even if I can't easily work 
> around the predicate at the end.
> 
> What's interesting is that the value query is slightly faster than the 
> element range query. I assume they're both using the range index, and the 
> value query is just doing it in less steps. 
> 
> Thanks for your help.
> 
> -Will
> 
> -----Original Message-----
> From: [email protected] 
> [mailto:[email protected]] On Behalf Of Will Thompson
> Sent: Wednesday, July 27, 2011 6:07 PM
> To: General MarkLogic Developer Discussion
> Subject: Re: [MarkLogic Dev General] xpath to cts query question
> 
> The data unfortunately won't allow for a more specific path. I was trying to 
> do something along the lines of what Mike suggested to utilize an attribute 
> range index, but the problem is that the cts:search will return multiple 
> documents because it includes ancestors, while the Xpath does not. 
> 
> Here's a less vague example:
> 
> //(chapter|subchapter|section)[@enum="123"] will only return, say, the 
> section that matches, 
> 
> but this:
> 
> cts:search(
>  doc(),
>  cts:element-attribute-range-query(
>    (xs:QName("chapter"), xs:QName("subchapter"), xs:QName("section")),
>    "=", 
>    xs:QName("enum"), $enum)
>  )
> ) 
> 
> will return the section and its ancestor chapter and subchapter, since they 
> are included in the searchable expression. The only way I could think to work 
> around this is separate queries, each with a searchable expression that 
> corresponds to the range query.
> 
> -Will
> 
> 
> -----Original Message-----
> From: [email protected] 
> [mailto:[email protected]] On Behalf Of Danny Sokolsky
> Sent: Wednesday, July 27, 2011 5:51 PM
> To: General MarkLogic Developer Discussion
> Subject: Re: [MarkLogic Dev General] xpath to cts query question
> 
> Another thing that might help is if you know the full path to the nodes.  
> With //, it will have to look for the nodes anywhere in the documents.  
> 
> -Danny
> 
> -----Original Message-----
> From: [email protected] 
> [mailto:[email protected]] On Behalf Of Michael Blakeley
> Sent: Wednesday, July 27, 2011 3:49 PM
> To: General MarkLogic Developer Discussion
> Subject: Re: [MarkLogic Dev General] xpath to cts query question
> 
> xdmp:plan help with that:
> 
> ...
>  <qry:info-trace>Analyzing path: 
>fn:collection()/descendant-or-self::node()/(a|b|c|d|e|f|g)[@foo = 
>"bar"]</qry:info-trace>
>  <qry:info-trace>Step 1 is searchable: fn:collection()</qry:info-trace>
>  <qry:info-trace>Step 2 does not use indexes: 
>descendant-or-self::node()</qry:info-trace>
>  <qry:info-trace>Step 3 is searchable: (a|b|c|d|e|f|g)[@foo = 
>"bar"]</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 3 predicate 1 contributed 1 constraint: @foo = 
>"bar"</qry:info-trace>
> ...
> 
> The cts:query would be something like:
> 
> xdmp:plan(
>  cts:search(doc(),
>    cts:element-attribute-value-query(
>      for $i in ('a', 'b', 'c', 'd', 'e', 'f', 'g')
>      return xs:QName($i),
>      xs:QName('foo'), 'bar')))
> 
> If that isn't fast enough, the next step might be an element-attribute range 
> index on every element-attribute combination, and switching to 
> cts:element-range-query with operator '='.
> 
> -- Mike
> 
> On 27 Jul 2011, at 15:36 , Will Thompson wrote:
> 
>> Thanks Danny. What I'm mainly trying to do is speed up some slow xpath. I've 
>> optimized a lot of this module, but this xpath seems to be one of the 
>> remaining bottlenecks: //(a|b|c|d|e|f|g)[@foo = "bar"]. I thought that by 
>> converting it to a cts:query it would be faster. Or is this Xpath already 
>> going to be optimized by MLS?
>> 
>> -Will
>> 
>> -----Original Message-----
>> From: [email protected] 
>> [mailto:[email protected]] On Behalf Of Danny Sokolsky
>> Sent: Wednesday, July 27, 2011 5:20 PM
>> To: General MarkLogic Developer Discussion
>> Subject: Re: [MarkLogic Dev General] xpath to cts query question
>> 
>> Hi Will,
>> 
>> I might not be understanding what you are doing here, but here are a few 
>> ideas.
>> 
>> I think you can use that XPath in the first arg of cts:search, as long as 
>> you do not put any variables in it.  Something like this:
>> 
>> cts:search(//(a|b|c|d|e|f|g)[@foo = "bar"], "hello")
>> 
>> Also, in cts:query, you can do a cts:element-query with the 
>> cts:element-attribute-query as its second arg.  Something like:
>> 
>> cts:element-query((xs:QName("a"), xs:QName("b")), 
>> cts:element-attribute-word-query((xs:QName("a"), 
>>     xs:QName("b")), xs:QName("foo"), "bar"))
>> 
>> -Danny
>> 
>> -----Original Message-----
>> From: [email protected] 
>> [mailto:[email protected]] On Behalf Of Will Thompson
>> Sent: Wednesday, July 27, 2011 2:51 PM
>> To: General MarkLogic Developer Discussion
>> Subject: [MarkLogic Dev General] xpath to cts query question
>> 
>> I'm trying to create the cts equivalent of essentially this:
>> 
>> //(a|b|c|d|e|f|g)[@attr = $val]
>> 
>> But it seems like I would have join multiple cts:search()s, one for each 
>> element, since I only want the matching element, and not its parent (so I 
>> can't do something like cts:search(//(a|b|c|d|e|f|g), 
>> cts:element-attribute-value-query((xs:QName("a"),...,(xs:QName("g")),xs:QName("attr"),$val)).
>> 
>> cts:search(//a, 
>> cts:element-attribute-value-query(xs:QName("a"),xs:QName("attr"),$val))
>> | cts:search(//b, 
>> cts:element-attribute-value-query(xs:QName("b"),xs:QName("attr"),$val))
>> | cts:search(//c, 
>> cts:element-attribute-value-query(xs:QName("c"),xs:QName("attr"),$val))
>> ...
>> | cts:search(//g, 
>> cts:element-attribute-value-query(xs:QName("g"),xs:QName("attr"),$val))
>> 
>> Is there a better way to do this?
>> 
>> Thank you!
>> 
>> -Will
>> _______________________________________________
>> General mailing list
>> [email protected]
>> http://developer.marklogic.com/mailman/listinfo/general
>> _______________________________________________
>> General mailing list
>> [email protected]
>> http://developer.marklogic.com/mailman/listinfo/general
>> _______________________________________________
>> General mailing list
>> [email protected]
>> http://developer.marklogic.com/mailman/listinfo/general
>> 
> 
> _______________________________________________
> General mailing list
> [email protected]
> http://developer.marklogic.com/mailman/listinfo/general
> _______________________________________________
> General mailing list
> [email protected]
> http://developer.marklogic.com/mailman/listinfo/general
> _______________________________________________
> General mailing list
> [email protected]
> http://developer.marklogic.com/mailman/listinfo/general
> _______________________________________________
> General mailing list
> [email protected]
> http://developer.marklogic.com/mailman/listinfo/general
> 

_______________________________________________
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