如何通过搜索许多大型文档有效地返回两个索引元素?

时间:2012-09-24 13:08:52

标签: xquery marklogic

我有一个包含数万个的marklogic(4.2)数据库 大型,复杂的(有些较小,但大的是10MB +) 正在以编程方式使用相当复杂的文档进行搜索的文档 构建搜索:搜索电话。在正常使用中,返回一些结果 时间使用分页,并生成匹配的片段,它的工作原理 精细。现在,其中一个客户端开发人员需要返回 all 即使在他构建了一个查询的情况下,也可以立即从该查询得到结果 返回DB中所有文档的查询。他最不在乎 但是比赛的内容;只有几个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 真慢

1 个答案:

答案 0 :(得分:1)

您可以尝试一些方法:流式搜索结果,共现事件和编码词典值。

您已经触及了编码的词典值,我认为这将是最有效的方法。它可能感觉像是一个黑客,但它是基于函数的索引的道德等价物。它应该很好地扩展。

同样使用范围索引和词典函数将是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/以了解这些错误。它可能需要在两侧进行一些棘手的编码,但这可以让你返回任意大的结果序列。