John
John

Reputation: 2852

XQuery resulting in Out Of Memory Error

Following is the XML file -

<Info>
  <Name>
    <P1>Tomy</P1>
    <P2>John</P2>
    <R>P2</R>
  </Name>
  <Name>
    <P1>Tomy</P1>
    <P2>John</P2>
    <R>P1</R>
  </Name>
  <Name>
    <P1>Rojer</P1>
    <P2>Messi</P2>
    <R>P2</R>
  </Name>
  <Name>
    <P1>Messi</P1>
    <P2>Carl</P2>
    <R>P2</R>
  </Name>
  <Name>
    <P1>Messi</P1>
    <P2/>
    <R>P1</R>
  </Name>

</Info>

P1 is the Player No 1 and P2 is the Player No 2, R is the result of the match. I want to list the names of Players in following format, with distinct occurences.

<P>Tomy V John</P>
<P>Rojer V Messi</P>
<P>Messi V John</P>
<P>Messi</P>

Following is the solution, which gives the desired output -

let $o := doc('sam')//Name
for $x in $o
  let $p := if (string-length($x/P2/text()) > 0) then concat($x/P1/text(),' Vs. ',$x/P2/text()) else $x/P1/text()
  for $y in $p
    group by $y
    order by $y
    return <a>{$y}</a>

But this query works better only for some selected records. In actual, I have 200000+ records, and when I execute this query, I get Out Of Memory Error. I am using BaseX 7.6.

If I remove the group by clause, the executes without error, but it gives the wrong result ie; with duplicate values. I need distinct result.

Any help ?

Upvotes: 0

Views: 844

Answers (2)

schlegel11
schlegel11

Reputation: 383

For anyone who is looking in this question, a possible solution for an out of memory behavior could be also a wrapping xml tag and the specific behavior of copying new nodes related to xQuery implementation e.g:

... <a>{$y}</a>

In that case something like this could also be the solution:

let $o := doc('sam')//Name
for $x in $o
  let $p := if (string-length($x/P2/text()) > 0) then concat($x/P1/text(),' Vs. ',$x/P2/text()) else $x/P1/text()
  for $y in $p
    group by $y
    order by $y
    return (# db:copynode false #) { <a>{$y}</a> }

For more please see this answer: https://stackoverflow.com/a/48887745/4825622

Upvotes: 0

Rameshwar Nagpure
Rameshwar Nagpure

Reputation: 174

Try this

  for $x in doc('sam')//Name
  let $p := if (string-length($x/P2/text()) > 0) then concat($x/P1/text(),' Vs. ',$x/P2  /text()) else $x/P1/text()
  group by $p
  order by $p
  return <a>{$p}</a>

Upvotes: 1

Related Questions