2017-05-24 37 views
1

我正在使用cts:element-value-match()在大量icd-10代码(超过70K项)中查找值。由于我们使用了字符串范围索引,结果很快就会返回。有没有快速的方法来找到匹配父节点的cts:element-value-match()?

项目的结构是这样的:

<item> 
    <value>E232</value> 
    <label>Diabetes insipidus</label> 
<item> 

这里是我如何打电话cts:element-value-match()样本:

cts:element-value-match(xs:QName("label"), '*diabetes*', $options) 

然而,cts:element-value-match()刚刚返回值的字符串。现在我需要一个快速的方法来找出这个值的父节点。我似乎可以这样做的唯一方法是使用非常慢的XPath表达式,并将字符串与文档中的每个标签进行比较。

let $value:= /codes/items/item[label = $label]/value 

是否有某种方式来获得结果字符串父节点?如果不是,我应该使用cts:element-value-match()以外的其他功能吗?或者,我应该创建一个结合值/标签对的字段并只搜索该字段?

回答

1

XPath不一定很慢,但确实涉及获取文档。以某种方式利用缓存可能是可能的。这可能有助于使用doc('/mycodes.xml')/codes/items/item[label = 'somelabel']/value等模式,必要时使用xdmp:value

虽然,更好的方法可能是重新考虑如何存储您的项目。如果您将每个文件存储在单独的文件中,则可以使用同现将其值与标签一起提取。

如果有理由不想触及你的代码结构,并且你可以使用MarkLogic 9,你也可以考虑使用TDE来构建一个视图,其中每个项目需要一行,并使用SQL或Optic API来查询它。

HTH!

+0

谢谢你的建议Mads。我尝试了你的建议并使用了doc()函数,但它仍然同样缓慢,因为尽管标签上有范围索引,但每次查找都必须进行70K以上的比较。我们正在使用ML-9,但并非我们所有的环境都升级了,而SQL和Optic API似乎有点矫枉过正。我意识到我可以将每个分割成一个单独的文件,然后使用cts:word-query(),但每个文件还有额外的800字节开销。我仍然在寻找构建一个复合元素来连接这两个值并在该元素上构建一个范围索引。 –

+0

我也考虑过三倍,可能值得一看。缺点是没有'cts:triple-match',但在SPARQL中有正则表达式和通配符选项。 – grtjn

1

我不知道为什么你开始一个值的匹配与范围查询,如果你需要超过价值回来开始。

你有没有试着用搜索表达式作用域的XPath和使用CTS:元素值范围查询()

类似:

cts:search(doc()/elements/element, cts:element-value-query(xs:QName("label"), '=', '*diabetes*') 

返回:

<item> 
    <value>E232</value> 
    <label>Diabetes insipidus</label> 
<item> 

如果你在item元素上有一个片段根,那么这应该是非常有效的。不过,我建议您考虑权衡片段根目录与重新构建数据。

你还提到你考虑过三倍。三元组有三个范围查询可以工作。

回到我的第一条语句 - 如果上述方法有效,那么最后可能在范围索引中没有什么价值,因为您可以通过元素词查询影响通用索引的通配符,例如。

1

谢谢你的建议。我没有意识到在cts:search的第一个参数的末尾添加XPath表达式会加快查询速度。但只要我不使用未经过滤的选项,它就会工作!我也尝试使用cts:element-value-match()和cts:word-query(),并发现单词查询更快。

我还发现添加cts:index-order()可以加快结果。

这是我最后的查询是什么样子:

let $q := xdmp:get-request-field('q', 'diabetes') let $start := xs:positiveInteger(xdmp:get-request-field('start', '1')) 
let $page-length := xs:positiveInteger(xdmp:get-request-field('start', '10')) 
let $end := $start + $page-length - 1 

let $results := cts:search(doc('/reference-data/icd-10-codes.xml')/codes/items/item, cts:word-query($q), ("filtered", cts:index-order(cts:element-reference(xs:QName("label")))))[$start to $end] 

这将返回在第二,这是我的“价值示范”足够好约1/10的结果的HTML表格视图阶段。我注意到我不得不使用“过滤”选项。如果根元素被用作cts:search()函数的第一个参数,那么“未过滤”选项似乎只能工作。所以我猜想完整的ICD-10文档仍然被加载到电子节点中。

如果生产中1/10秒的时间太长,我们可以将文件分解成70K个小文件。

再次感谢Mads和David!

相关问题