最有效的方法来计算XQuery中多个值的出现次数

Bra*_*roy 5 xml perl xpath xquery basex

我有1581个单词需要在荷兰语的XML语料库中查找(5亿字).该语料库本身在许多数据库中被分开.(你可以在这里阅读原因.)我们使用BaseX作为服务器(版本7.9),它使用XQuery作为输入.

我感兴趣的是找出每个字有多少次是在用中性判断(胼HET)或非中性判断() -这是通过查找由一个NP(名词短语)的XPath的结构做了哪些有两个女儿,一个带有lemma dehet的限定词,和一个头,这是我感兴趣的词.

de的示例结构

/node[@cat="np" and node[@rel="det" and @pt="lid" and @lemma="de"] and node[@rel="hd" and @pt="n" and @word="accelerator"]]
/node[@cat="np" and node[@rel="det" and @pt="lid" and @lemma="de"] and node[@rel="hd" and @pt="n" and @word="accountant"]]
/node[@cat="np" and node[@rel="det" and @pt="lid" and @lemma="de"] and node[@rel="hd" and @pt="n" and @word="ace"]]
/node[@cat="np" and node[@rel="det" and @pt="lid" and @lemma="de"] and node[@rel="hd" and @pt="n" and @word="acroniem"]]
Run Code Online (Sandbox Code Playgroud)

het的示例结构

/node[@cat="np" and node[@rel="det" and @pt="lid" and @lemma="het"] and node[@rel="hd" and @pt="n" and @word="accelerator"]]
/node[@cat="np" and node[@rel="det" and @pt="lid" and @lemma="het"] and node[@rel="hd" and @pt="n" and @word="accountant"]]
/node[@cat="np" and node[@rel="det" and @pt="lid" and @lemma="het"] and node[@rel="hd" and @pt="n" and @word="ace"]]
/node[@cat="np" and node[@rel="det" and @pt="lid" and @lemma="het"] and node[@rel="hd" and @pt="n" and @word="acroniem"]]
Run Code Online (Sandbox Code Playgroud)

在XQuery中,我会这样做,对于每个XPath结构:

count(for $node in db:open("mydatabase")/treebank/tree/node[@cat="np" and node[@rel="det" and @pt="lid" and @lemma="het"] and node[@rel="hd" and @pt="n" and @word="accelerator"]] return $node)
Run Code Online (Sandbox Code Playgroud)

这很好用.问题是,这需要很长时间.每次都需要按顺序打开相同(数千个)数据库,并对每个单词重复此过程.我的问题是,是不是有办法连接一些查询.我有一些想法,但我不确定如何执行它们 - 另外,我不确定BaseX可以处理多少个参数.

  1. 合并dehet查询.

这可能是最简单的情况.通过这样做,我至少减少了一半的查询需求.但我不知道在找到结果时如何区分这两者.例如,如果我将我的XPath代码更改为:

... (@lemma="de" or @lemma="het") ...
Run Code Online (Sandbox Code Playgroud)

我应该找到所有案例,但我怎么能区分其中一个呢?换句话说,如果我使用了XPath,我会得到一个数的计数功能回到XQuery的,但没有办法,我知道这是和它们

  1. 相同的想法可以应用于接近结尾的单词属性

我可以将它们连接起来,而不是为每个单词执行新的查询:

... (@word="accelerator" or @word="accountant" or @word="ace" or ...) ...
Run Code Online (Sandbox Code Playgroud)

但同样,我如何区分这些价值观呢?我可以将所有1581值放在一个XPath中吗?BaseX可以处理吗?

  1. 一个for循环,带有一个单词列表,然后以XML格式返回结果中的很多单词(如果BaseX可以处理的话,可能全部).

我不是XQuery的专家,但在伪代码中,我猜这样的事情是可能的:

$wordlist = ['accelerator', 'accountant', 'ace', 'acroniem'];
$determinerlist = ['de', 'het'];
$db = 'mydatabase';
foreach ($wordlist as $word) {
  foreach ($determinerlist as $det) {
    count(for $node in db:open("'.$db.'")/treebank/tree/node[@cat="np" and node[@rel="det" and @pt="lid" and @lemma="'.$det.'"] and node[@rel="hd" and @pt="n" and @word="'.$word.'"]] return $node);
  }
}
Run Code Online (Sandbox Code Playgroud)

我不确定如何将计数分配给XQuery中的数组变量,如果可能的话,但XML输出可能看起来像这样(但当然欢迎更好的变体):

<results>
  <result word="accelerator">
    <neuter>12</neuter>
    <nonneuter>3</nonneuter>
  </result>
  <result word="accountant">
    <neuter>4</neuter>
    <nonneuter>0</nonneuter>
  </result>
  <result word="ace">
    <neuter>14</neuter>
    <nonneuter>2</nonneuter>
  </result>
  <result word="acroniem">
    <neuter>3</neuter>
    <nonneuter>7</nonneuter>
  </result>
</results>
Run Code Online (Sandbox Code Playgroud)

然后,我可以使用带有正则表达式或XML twig的Perl来获取我需要的值.

正如你可以看到5月号的是找到一个合适的XQuery代码是有效的,而且考虑到我有1581个字,巨大的语料库来查找帐户,而数据库的数量要经过很多以及(千).对于每个数据库查找,通过Perl建立新连接.

如果您有任何疑问,请发表评论,我会尽可能地回答.

Cho*_*ops 1

一般来说,如果您利用索引而不是让查询遍历一万亿个节点,那么 BaseX 查询将是最快的(通常快得令人眼花缭乱)。BaseX 默认为您创建 TEXT、ATTRIBUTE 和 TOKEN 索引,除非您修改了默认的数据库创建选项。(BaseX 还尝试重写查询以利用索引 - 尽管它并不总是成功)。

因此,假设您的数据库是使用 ATTRIBUTE 索引构建的,您应该能够按照以下方式重写查询:

db:attribute('dbname', 'accelerator', 'word')/parent::*
Run Code Online (Sandbox Code Playgroud)

对于数据库“dbname”,上面使用的 db:attribute 函数将返回任何以“accelerator”作为 @word 值的属性的父元素。显然,从前面的示例来看,您可以根据需要尽可能多地谓词此查询,如下所示:

db:attribute('dbname', 'accelerator', 'word')
      [parent::node[@rel="hd" and @pt="n"]]
      [ancestor::node
        [@cat="np"]
        [child::node[@rel="det" and @pt="lid" and @lemma="het"]
      ]
    ]
Run Code Online (Sandbox Code Playgroud)

这里有关于 BaseX 索引功能的很好的文档。我使用它对大型(> 20 GB)数据库的速度查询产生了巨大的影响。

http://docs.basex.org/wiki/Indexes