Tim,

You should be able to use the indexes if you can enumerate the parent element names. Let's start with some test docs....

(: build test case :)
let $names :=
  for $i in 1 to 8
  return codepoints-to-string(string-to-codepoints("a") - 1 + $i)
for $i in 1 to 100
let $name-index := 1 + $i count($names)
let $id := concat("t", string($i))
let $uri := concat("test/", string($i))
return
  xdmp:document-insert(
    $uri,
    element { $names[$name-index] } {
      attribute xml:id { $id },
      xdmp:integer-to-hex(xdmp:random())
    })

This inserts 100 docs that look like:

...
<a xml:id="t16">39c5218f30d8434f</a>
<b xml:id="t17">74fb0615f8a17110</b>
<c xml:id="t10">53439ea8dd47f4d0</c>
<d xml:id="t11">828dd36894cfa367</d>
<e xml:id="t12">87d537f4eb96e1b0</e>
<f xml:id="t13">154eea3e15b59fcf</f>
<g xml:id="t14">701dfd435977a3fc</g>
<h xml:id="t15">39842113ea1e916e</h>
...

I can query these documents efficiently using XPath:

/(a|b|c|d|e|f|g|h)[...@xml:id eq "t1"]
=>
<b xml:id="t1">60271146593168d7</b>

According to xdmp:query-trace(), this selects 1 fragment to filter. We can also write this query in a few other ways. For example, I might want to store a list of all the possible QNames in a variable, so that I can compose the query more dynamically:

let $names :=
  for $i in 1 to 8
  return xs:QName(codepoints-to-string(string-to-codepoints('a') - 1 + $i))
return /*[node-name(.) = $name...@xml:id eq "t1"]

We can use a similar technique with a cts:query:

let $q :=
  cts:element-attribute-value-query(
    for $i in 1 to 8
    return
      xs:QName(
        codepoints-to-string(
          string-to-codepoints("a") - 1 + $i)),
    xs:QName("xml:id"),
    "t1")
return cts:search(doc(), $q)

All three of these forms are efficient.

thanks,
-- Mike

On 2009-07-20 19:02, Tim Finney wrote:
Dear All,

I would like to be able to find the element associated with an @xml:id
quickly, without knowing the element path or name. Can this be done with
MarkLogic?

The id() function is meant to do this but it is horribly slow when faced
with masses of documents. For example,

collection()//*...@xml:id eq 'something']

takes thirty seconds and I need it to work in hundredths of seconds
instead.

(If I put in the element name, the above query runs in about a hundredth
of a second.)

Best,

Tim Finney
University of Virginia Press


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

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

Reply via email to