【问题标题】:wildcard search on triples in MarkLogic在 MarkLogic 中对三元组进行通配符搜索
【发布时间】:2018-08-07 11:28:51
【问题描述】:

是否可以使用cts 查询对三元组执行通配符搜索?

我已经在sparql 中尝试过,我得到了正确的结果,但是查询很慢。

例如:

PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
select ?iri
where {
   ?iri skos:prefLabel ?prefLabel .
   filter (STRSTARTS(lcase(?prefLabel), 'soviet'))
} limit 250

上面的查询返回了正确的结果,但是查询非常慢。

因为我正在构建一个自动建议 API,它应该非常快。

请帮忙。

戴夫评论后更新:

我尝试了第二种方法,它比前一种方法好,但速度没有那么快。 cts filtered 查询运行有点慢,我们无法在当前 xml 结构上进行 unfiltered 搜索。

在项目中,我们需要非常快速的建议,因此我尝试了以下方法。

我为每个主题创建了如下所述的 XML 文件

<record>
    <pref-label>Dixit Singla</pref-label>
    <iri>prefix:12345</iri>
</record>

现在使用cts:element-values on iri element 并使用wildcarded cts:element-value-query on pref-label 过滤它,我得到所有匹配的虹膜并将它们传递给sparql 查询。通过这个,我可以看到很大的性能提升。

cts:element-values(xs:QName('iri'), (),(), cts:element-value-query(xs:QName('pref-label'), 'sov* *'))

我知道上述方法会消耗更多内存,但这很好,因为性能非常好:)

观察:当主题通过sparql 时,它运行得非常快。

喜欢:

PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
select ?iri
where {
   values ?iri {prefix:12345 prefix:12346 prefix:12339 prefix:12345}
   ?iri skos:prefLabel ?prefLabel .
   #apply filters
} limit 250

【问题讨论】:

  • 如果没有全文索引,您在 SPARQL 中大多会丢失,因为必须对中间结果进行全扫描 + 过滤。 Marklogic 是否支持全文搜索功能?如果是这样,请使用它
  • 好的,cts:contains 在 SPARQL 中原生工作。您可以尝试cts:search 是否也可以,然后使用XQuery 表达式。我这里没有 Marklogic 服务器
  • XPath 通过fn: 前缀也是可以的,但是如果这里没有使用全文索引,那么检查字符串开始仍然会很昂贵
  • 您使用的是托管三元组还是嵌入式三元组?
  • 托管三元组。

标签: sparql marklogic


【解决方案1】:

此答案中列出了两种方法


试试这个:

sem:sparql(
  "PREFIX skos: <http://www.w3.org/2004/02/skos/core#>
   select ?iri
   where {
      ?iri skos:prefLabel ?prefLabel .
      filter (STRSTARTS(lcase(?prefLabel), 'soviet'))
   } limit 250",
  (),
  (),
  sem:store("any", cts:element-query(xs:QName("sem:object"), cts:word-query("soviet*")))
)

sem:store 标识一组三元组。通过传入单词查询,我们只找到出现在包含以“soviet”开头的&lt;sem:object&gt; 的文档中的那些三元组。

即使是托管三元组在文档中也显示为 XML 或 JSON。当您插入托管三元组时,MarkLogic 决定如何将它们分成文件。如果您有很多三元组,这种方法应该会减少 SPARQL 查询所针对的数量。


基于@grtjn 的 cmets 的编辑:

  • 是的,应该是“soviet*”——已修复
  • 如前所述,这种方法之所以有效,是因为 SPARQL 查询非常简单——它只查找具有特定对象模式的三元组。如果 SPARQL 查询需要连接到其他三元组,这将不起作用,因为这些三元组很可能已被 sem:store 调用排除在外。

第二种方法。目标是对对象进行通配符搜索,然后获取主题 IRI 并将其传递给 SPARQL 查询。

由于这些是托管三元组,我们知道它们将位于根为 sem:triples 的 XML 文档中,并且每个三元组将表示如下:

<sem:triple> <sem:subject>http://example.com/my-subject</sem:subject> <sem:predicate>http://example.com/my-predicate</sem:predicate> <sem:object datatype="http://www.w3.org/2001/XMLSchema#string">my-object</sem:object> </sem:triple>

我们可以创建一个以对象字符串为目标的通配符查询:

cts:element-value-query(xs:QName("sem:object"), "soviet *", "wildcarded")

注意“soviet”和“*”之间的空格。 cts:element-value-query 的文档解释了原因:

请注意,cts:element-value-query 中值的文本内容被视为与 cts:word-query 中的短语相同,其中短语是元素值。因此,任何通配符和/或词干规则都被视为短语。例如,如果您有一个为查询启用通配符的元素值“hellofriend”,则“he*”的 cts:element-value-query 将不匹配,因为通配符匹配不跨越单词边界,但 cts :element-value-query for "hello " 将匹配。搜索“”将匹配,因为“*”通配符本身被定义为匹配该值。类似地,词干规则适用于每个术语,因此当为查询启用词干提取时,搜索“hello friends”将匹配,因为“friends”匹配“friend”。

您可能想改用cts:element-word-query

然后我们可以在cts:search 上使用$expression 参数来确保我们只得到我们想要的三元组。请注意,这需要过滤。一旦我们有了三元组,我们就可以使用 XPath 来获取主题,然后将它们传递给 SPARQL 查询。

将所有这些放在一起,我们得到:

let $query := cts:element-value-query(xs:QName("sem:object"), "soviet *")
let $subjects := cts:search(/sem:triples/sem:triple, $query)/sem:subject/fn:string()

将您的 $subjects 传递到您的 SPARQL 查询中,然后就可以使用了。这应该有效;我剩下的问题是它是否比你开始的更快。我很想听听你的测试结果。

【讨论】:

  • 不应该是"soviet*"吗?
  • 带有 cts:query 的 sem:store 可以显着减少 sparql 引擎评估的三元组,从而提供巨大的性能改进,但请注意不要排除您可能需要的三元组。无法保证哪些三元组在 MarkLogic '管理'的三元组中持久保存。
  • @dave 感谢您的回复,但我不能使用“存储”,因为我还必须连接到其他三元组(正如您已经提到的),我必须过滤其他一些三元组sparql 中的谓词也是如此。有没有其他方法,比如使用cts:search wildcarded 功能来获取主题 IRI 并在 sparql 查询中传递这些 iris。
  • @DixitSingla 请参阅上面的第二种方法
  • @DaveCassel 我尝试了第二种方法。请查看“戴夫评论后更新”部分。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-16
  • 1970-01-01
相关资源
最近更新 更多