0

我有一个 marklogic (4.2) 数据库,其中包含数以万计的大型、复杂(有些较小,但大的是 10MB+)文档,这些文档正在使用相当复杂的、以编程方式构建的 search:search 调用进行搜索. 在正常使用中,使用分页一次返回几个结果,并生成匹配的片段,它工作正常。现在,其中一位客户端开发人员需要一次返回该查询的所有结果,即使在他构建了一个返回数据库中所有文档的查询的情况下也是如此。不过,他并不关心比赛的大部分内容。只有几个 ID 元素(一个数字和一个自由文本),它们都被索引,并且它们总是在文档中的相同 xpath 中。

问题是,我无法想出一种有效的方法来查询这么大的数据集中的两个元素。它总是需要加载整个文档,而查询只是在长草中消失了几万次,并且基本上永远不会返回。

我尝试在其中一个元素上使用元素值词典,并通过搜索过滤。这很快就会返回,但有几个缺点: * 它返回误报。这不一定会破坏交易,但不是最理想的。* 它只获取其中一个元素;一旦我尝试迭代该列表并获取他感兴趣的另一个元素,不出所料地需要永远(因为我们要为每次匹配加载整个文档。)

我想知道是否声明一个包含这两个元素的字段可能会有所帮助(我可以使用词典来获取其中一个值,然后在该字段中查找它,而不是加载整个文档来获取一个 ID,)但我以前从未使用过字段,而且看起来它们总是单词查询,而不是元素查询,这对于我需要用它们做的事情来说听起来并不理想。

我还认为可能在文档中创建一个新元素,其中包含两个 ID 的编码形式,这将允许我创建一个包含两者的索引,然后使用我上面提到的词典方法将其缩小到至少匹配的文档未过滤的搜索。不过,这感觉像是一种非常老套的方法。

我真正在寻找的是一种方式来表达“这是一个搜索,这里是我感兴趣的(索引)元素,现在获取它们的值以匹配文档”。有没有办法做到这一点?

我觉得答案是“不”,但值得一问。

如果没有,是否有人对哪些替代方法可能最有效提出建议?

谢谢。


文档格式示例:

<doc:entity>
  <doc:metadata>
    <doc:sap-metadata>
      <doc:info>
        <doc:id>12345678</doc:id>
        <doc:number>AS-1990 13:45</doc:number>
        <!-- more document info here -->
      </doc:info>
    </doc:sap-metadata>
  </doc:metadata>
  <doc:content>
    <!-- a lot of text content here... -->
  </doc:content>
</doc:entity>

搜索代码(初剪):

搜索代码一点也不聪明。只是一个标准的搜索:带有搜索词的搜索调用和(至少一个约束 - 为了清楚起见,我坚持简单的情况):

search:search(fn:concat("relevant:1 ", $search-term), $search-options)

$search-term是用户提供的明文搜索。$search-options是相当多的xml,但我不认为包含任何异国情调;只是一堆约束和方面定义和自定义片段,由以下生成:

declare function func:do-snippet(
  $result as node(),
  $ctsquery as schema-element(cts:query),
  $options as element(search:transform-results)?
) as element(search:snippet)
{
  element search:snippet{
    element search:match {
      fn:doc(xdmp:node-uri($result))/doc:entity/doc:metadata/doc:sap-metadata/doc:info/doc:id,
      fn:doc(xdmp:node-uri($result))/doc:entity/doc:metadata/doc:sap-metadata/doc:info/doc:number
    }
  }
};

搜索代码(第二切):

这个是使用 id 上的 element-value-lexicon 生成与搜索词匹配的 ID 列表(显然未过滤),然后使用该 id 查询文档编号:

let $query := ...
let $options := ...
for $id in cts:element-values(fn:QName("http://my.document.namespace", "id"), (), (), cts:query(search:parse($query, $options)))
  return element document {
    attribute id {$id},
    attribute number {
      cts:element-values(fn:QName("http://my.document/namespace", "number"), (), (), cts:element-value-query(fn:QName("http://my.document.namespace", "id"), $id ))
    }}

第一个cts:element-values调用返回很好而且很快,但是迭代响应并cts:element-values为每个响应做另一个真的很慢。

4

1 回答 1

1

您可以尝试几种方法:流式传输结果、共现和编码的词典值。

您已经接触过编码的词典值,我认为这将是最有效的方法。它可能感觉像是一种 hack,但它在道德上等同于基于函数的索引。它应该可以很好地扩展。

还使用范围索引和词典函数将是cts:element-value-co-occurrences. 这不会像编码值那样缩放,但它的前期工作较少。一定要考虑“地图”选项:http ://docs.marklogic.com/cts:element-value-co-occurrences

最后,您可以简单地给开发人员他想要的东西。用于search:parse正常解析查询,或使用cts:query构造函数构建它。然后调用cts:search以获取匹配的节点并返回它们。结果会很大,但这是不可避免的。您可能会遇到XDMP-EXPNTREECACHEFULL错误:查看http://blakeley.com/blogofile/2012/03/19/let-free-style-and-streaming/以了解其中的一种方法。它可能需要在双方进行一些棘手的编码,但这可以让您返回任意大的结果序列。

于 2012-09-24T14:27:25.117 回答