0

次のコードが私のデータの小さなセットで機能することがわかりましたが、複数のコメントを含むサンプルを取得していないことに気づきませんでした。エントリごとに複数のコメントがある実際のデータベースにコードを適用しようとすると、上記のエラーが発生しました。

現在のコード:

for $doc in doc('test')
let $results :=
(
  let $pKeywords := ('best clients', 'Very', '20')
  return
    for $kw in $pKeywords
    return
    (
      $doc/set/entry[contains(comment, concat('!', $kw))],
      $doc/set/entry[contains(comment, $kw)]
    )
  [not(position() gt 2)]
)
for $i in (1 to count($results))
return
(
  subsequence($results/comment, $i, 1),
  subsequence($results/buyer, $i, 1)
)

書類:

<set>
  <entry>
    <comment>The client is only 20 years old.  Do not be surprised by his youth.</comment>
    <buyer></buyer>
    <id>1282</id>
    <industry>International Trade; Fish and Game</industry>
  </entry>
  <entry>
    <comment>!On leave in October.</comment>
    <comment>!Planning to make a large purchase before Christmas.</comment>
    <buyer></buyer>
    <id>709</id>
    <industry>Real Estate</industry>
  </entry>
    <entry>
    <comment>Is often !out between 1 and 3 p.m.</comment>
    <buyer></buyer>
    <id>127</id>
    <industry>Virus Software Marketting</industry>
  </entry>
  <entry>
    <comment>Very personable.  One of our best clients.</comment>
    <buyer></buyer>
    <id>14851</id>
    <industry>Administrative support.</industry>
  </entry>
  <entry>
    <comment>!Very difficult to reach, but one of our top buyers.</comment>
    <comment>His wife often answers the phone.  That means he is out of the office.</comment>
    <buyer></buyer>
    <id>1458</id>
    <industry>Construction</industry>
  </entry>
  <entry>
    <comment></comment>
    <buyer></buyer>
    <id>276470</id>
    <industry>Bulk Furniture Sales</industry>
  </entry>
  <entry>
    <comment>A bit of an eccentric.  One of our best clients.</comment>
    <buyer></buyer>
    <id>1506</id>
    <industry>Sports Analysis</industry>
  </entry>
  <entry>
    <comment>Very gullible, so please !be sure she needs what you sell her.  She's one of our best clients.</comment>
    <buyer></buyer>
    <id>1523</id>
    <industry>International Trade</industry>
  </entry>
  <entry>
    <comment>He wants to buy everything, but !he has a tight budget.</comment>
    <comment>!His company may be closing soon.</comment>
    <buyer></buyer>
    <id>1524</id>
    <industry>Public Relations</industry>
  </entry>
</set>

結果:

Stopped at line 9, column 22: [XPTY0004] document-node()(...): function(item()*) as item()* expected, document-node() found.

同様のエラーが発生して修正できましたが、修正を適用しようとするとうまくいきませんでした。例:

  $doc('test')/set/entry[contains(., concat('!', $kw))],
  $doc('test')/set/entry[contains(., $kw)]

同じ結果を返します。

目的の結果をたどる:

エントリの子に の 3 つのキーワードのいずれかが含まれている場合、最初のエントリはすべてとその子returnを返す必要があります。entrycomment$pKeywords

concat('!', $kw)! を含むコメントを優先することになっています。

2 番目は、最初の の結果からおよびノードをreturnスライスします。commentbuyerreturn

commentすべてのエントリに という名前のノードが1 つだけ存在する限り、コードは正常に実行されます。という名前のノードが 2 つ以上あるcomment場合、コードは失敗し、コンパイラは上記のエラーを返します。

Stopped at line 9, column 22: [XPTY0004] document-node()(...): function(item()*) as item()* expected, document-node() found.

-編集-

望ましい結果:

<comment>The client is only 20 years old.  Do not be surprised by his youth.</comment>
<buyer/>
<comment>Very personable.  One of our best clients.</comment>
<buyer/>
<comment>!Very difficult to reach, but one of our top buyers.</comment>
<buyer/>
<comment>A bit of an eccentric.  One of our best clients.</comment>
<buyer/>

望ましい結果を明確にする:

//contains ! and the first keyword, "best clients"; so, the first result should come from this entry.
  <entry>
    <comment>Very gullible, so please !be sure she needs what you sell her.  She's one of our best clients.</comment>
    <buyer></buyer>
    <id>1523</id>
    <industry>International Trade</industry>
  </entry>

//Only one entry contains ! and "best clients".  So, the first result containing "best clients" contains nodes for the second result.
  <entry>
    <comment>Very personable.  One of our best clients.</comment>
    <buyer></buyer>
    <id>14851</id>
    <industry>Administrative support.</industry>
  </entry>

//This contains ! and the second keyword, "Very", but it is a duplicate.  So, ideally its children should not be returned.
  <entry>
    <comment>!Very difficult to reach, but one of our top buyers.</comment>
    <comment>His wife often answers the phone.  That means he is out of the office.</comment>
    <buyer></buyer>
    <id>1458</id>
    <industry>Construction</industry>
  </entry>

//This contains ! and a string, "very" (part of everything).  Nodes from this entry should be returned as the third result.
  <entry>
    <comment>He wants to buy everything, but !he has a tight budget.</comment>
    <comment>!His company may be closing soon.</comment>
    <buyer></buyer>
    <id>1524</id>
    <industry>Public Relations</industry>
  </entry>

//The only entry whose comment child contains the keyword '20'.  There is no '!'-containing comment with 20, so this nodes is the top and only node whose children should be returned.
  <entry>
    <comment>The client is only 20 years old.  Do not be surprised by his youth.</comment>
    <buyer></buyer>
    <id>1282</id>
    <industry>International Trade; Fish and Game</industry>
  </entry>

-編集2-

次のパスでは、何を達成しようとしているのかをよりよく理解できますが、明らかな構文エラーがいくつかあります (たとえば、8 行目に見られるように、配列の操作方法をまだ発見していません)。構文エラーを解決したら、これを更新します。

<set>
{
    let $kw := ('best clients', 'Very', '20')
    let $entry := doc('test')/set/entry
    let $priority := '!'

    for $i in (1, count($kw))
    let $priority_result[$i] :=
    (
        for $entries in $entry
        where $entry contains(., $priority) and where $entry contains $kw[$i]
        return subsequence($priority_result[$i], 1, 2)
    )

    if $priority_result[$i] < 2
    for $i in (1, count($kw))
    let $secondary_result[$i] :=
    (
        for $entries in $entry
        where $entry contains $kw[$i] and where $entry not($priority_result) and where $entry not($secondary_result[1..($i-1)])
        return $secondary_result[$i]
    )
    else let $secondary_result[$i] := ''

    for $i in (1, count($kw))
    return
    (
        $primary_result[$i],
        $secondary_result[$i]
    )
}
</set>

そして、null の結果を返す提案された変更:

for $doc in doc('test')
let $results :=
(
  let $pKeywords := ('best clients', 'Very', '20')
  return
    for $kw in $pKeywords
    return
    (
      $doc/set/entry/comment[contains(., concat('!', $kw))],
      $doc/set/entry/comment[contains(., $kw)]
    )
  [not(position() gt 2)]
)
for $i in (1 to count($results))
return
(
  subsequence($results/comment, $i, 1),
  subsequence($results/buyer, $i, 1)
)
4

2 に答える 2

1

document-node()エラーメッセージは、 a を関数として呼び出そうとしていることについて不平を言っているようです。

$doc('test')$doc


それかcomments(...)、ノードセットではなく、単一のノードでのみ機能します。

contains(comment, $kw)comment/contains(.,$kw)
またはcomment[contains(.,$kw)]
またはcomment[contains(text(),$kw)]


これは私のために働いた:

<set>{
    for $entry in doc('test')/set/entry
    let $kw := (
        for $prefix in ('!','')
        for $kw in ('best clients', 'Very', '20')
        where exists($entry/comment[contains(., concat($prefix,$kw))])
        return concat($prefix,$kw)
    )[1]
    where exists($kw)
    order by not(starts-with($kw,'!'))
    return <entry keyword="{$kw}">{
      ( $entry/comment,
        $entry/buyer )
    }</entry>
}</set>

結果 ( ごとに複数のコメント<entry>):

<set>
   <entry keyword="!Very">
      <comment>!Very difficult to reach, but one of our top buyers.</comment>
      <comment>His wife often answers the phone.  That means he is out of the office.</comment>
      <buyer/>
   </entry>
   <entry keyword="20">
      <comment>The client is only 20 years old.  Do not be surprised by his youth.</comment>
      <buyer/>
   </entry>
   <entry keyword="best clients">
      <comment>Very personable.  One of our best clients.</comment>
      <buyer/>
   </entry>
   <entry keyword="best clients">
      <comment>A bit of an eccentric.  One of our best clients.</comment>
      <buyer/>
   </entry>
   <entry keyword="best clients">
      <comment>Very gullible, so please !be sure she needs what you sell her.  She's one of our best clients.</comment>
      <buyer/>
   </entry>
</set>

これにより、コメントごとに個別のエントリが得られます。

<set>{
    for $entry in doc('test')/set/entry
    for $comment in $entry/comment
    let $kw := (
        for $prefix in ('!','')
        for $kw in ('best clients', 'Very', '20')
        where exists($comment[contains(., concat($prefix,$kw))])
        return concat($prefix,$kw)
    )[1]
    where exists($kw)
    order by not(starts-with($kw,'!'))
    return <entry keyword="{$kw}">{
      ( $comment,
        $entry/buyer )
    }</entry>
}</set>

出力:

<set>
   <entry keyword="!Very">
      <comment>!Very difficult to reach, but one of our top buyers.</comment>
      <buyer/>
   </entry>
   <entry keyword="20">
      <comment>The client is only 20 years old.  Do not be surprised by his youth.</comment>
      <buyer/>
   </entry>
   <entry keyword="best clients">
      <comment>Very personable.  One of our best clients.</comment>
      <buyer/>
   </entry>
   <entry keyword="best clients">
      <comment>A bit of an eccentric.  One of our best clients.</comment>
      <buyer/>
   </entry>
   <entry keyword="best clients">
      <comment>Very gullible, so please !be sure she needs what you sell her.  She's one of our best clients.</comment>
      <buyer/>
   </entry>
</set>
于 2012-10-01T05:50:09.150 に答える
0

参考までに、これが最初のコードです (少し難しいので、まだすべてを理解していません)。

for $doc in doc('test')
let $results :=
(
  let $pKeywords := ('best clients', 'Very', '20')
  return
    for $kw in $pKeywords
    return
    (
      $doc/set/entry[contains(comment, concat('!', $kw))],  (: *1 :)
      $doc/set/entry[contains(comment, $kw)]                (: *1 :)
    )
  [not(position() gt 2)]
)
for $i in (1 to count($results))
return
(
  subsequence($results/comment, $i, 1), (: *2 :)
  subsequence($results/buyer, $i, 1)    (: *2 :)
)

エラーをスローしないバージョンは、通常の方法で解決されます。でマークされた 2 番目のエラーをキャッチするのにしばらく時間がかかりました*2。基本的に、検索で 1 レベル深く行ったので*1、結果を 1 レベル上げる必要がありました..

for $doc in doc('test')
let $results :=
(
  let $pKeywords := ('best clients', 'Very', '20')
  return
    for $kw in $pKeywords
    return
    (
      $doc/set/entry/comment[contains(., concat('!', $kw))], (: *1, went deeper :)
      $doc/set/entry/comment[contains(., $kw)]               (: *1, went deeper :)
    )
  [not(position() gt 2)]
)
for $i in (1 to count($results))
return
(
  subsequence($results/../comment, $i, 1), (: *2, added .. :)
  subsequence($results/../buyer, $i, 1)    (: *2, added .. :)
)

私がまだ苦労していること:

1) の使用concat()。私の理解では、それは2つのことをまとめており、その結果$kw[1]は と同等"!best clients"です。しかし、結果はそれを示していません。その結果、感嘆符は優先クエリの直前にあるとは限りません。

2) 重複した結果を返さない。すべてのエントリが一意であることを望みます。重複が結果セットに入るのを制限するか、結果[not(position() gt 2)]の数がトリミング/スライスされる前に重複を排除するルーチンをどこかに追加する必要があります。

すべての視聴者と作品への努力に感謝します!より良い答えを楽しみにしています!

于 2012-10-02T11:31:52.683 に答える