在MarkLogic中对三元组进行通配符搜索

时间:2018-08-07 11:28:52

标签: sparql marklogic

是否可以使用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,因此应该很快。

请帮助。

在daves评论后更新:

我已经尝试了第二种方法,它比前一种更好,但速度却不那么快。 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

1 个答案:

答案 0 :(得分:3)

此答案中列出了两种方法


尝试一下:

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标识一组三元组。通过传递单词查询,我们发现包含以“苏联”开头的<sem:object>的文档中出现的那些三元组。

甚至托管的三元组在文档中也显示为XML或JSON。当插入托管三元组时,MarkLogic决定如何将它们分成文件。如果您有很多三元组,则此方法应减少针对SPARQL查询运行的数量。


根据@grtjn的评论进行编辑:

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

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

由于这些是可管理的三元组,因此我们知道它们将在XML文档中,其根为sem:triples,并且每个三元组都将这样表示:

<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")

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

  

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

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

然后我们可以在$expression上使用cts:search参数,以确保仅获得所需的三元组。请注意,这需要过滤。一旦有了三元组,就可以使用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查询中,然后离开。这应该起作用;我剩下的问题是它是否比开始时要快。我很想听听您的测试结果。