SPARQL 地理空间查询 (MarkLogic)

SPARQL Geospatial Queries (MarkLogic)

继续上一个问题 here。有人指出,在 SPARQL 查询中应避免使用 fn:doc()。但是,除了下面显示的代码之外,对于地理空间查询,我无法找到替代解决方案。我也使用过这个查询,它的运行时间真的很慢。对于更大的数据集,它将达到 1 小时超时。

因此,我想问一下是否有更好的方法来实现 SPARQL 的地理空间查询?是否可以将 GEOSPARQL 与 PREFIX spatial:<http://jena.apache.org/spatial#> 一起使用?

xquery version "1.0-ml";
import module namespace sem = "http://marklogic.com/semantics" at "/MarkLogic/semantics.xqy";
import module namespace thsr="http://marklogic.com/xdmp/thesaurus" 
                             at "/MarkLogic/thesaurus.xqy";

let $query := sem:sparql(
'
PREFIX xs: <http://www.w3.org/2001/XMLSchema#>
PREFIX cts: <http://marklogic.com/cts#>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema/>
PREFIX fn: <http://www.w3.org/2005/xpath-functions#>
PREFIX foaf: <http://xmlns.com/foaf/0.1/>
PREFIX dc: <http://purl.org/dc/elements/1.1/>
PREFIX db: <http://dbpedia.org/resource/>
PREFIX onto: <http://dbpedia.org/ontology/>
PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>
PREFIX xdmp: <http://marklogic.com/xdmp#>

SELECT *
WHERE{
?people </posted> ?question .
FILTER (cts:contains(fn:doc(?people), 
cts:path-geospatial-query("/people_data/location",  cts:circle(10, cts:point(59,28)))
)) .
}',
(),
(),
()
)

return (xdmp:elapsed-time())

=======更新========

问题提交给

我在这里看到两个选项:

  • 要么使用 MarkLogic 内置的地理空间函数直接从 SPARQL 内部查找地理空间重叠,最好是比较 RDF 属性,而不是路径索引中的值(仍然 sub-optimal )
  • 更好:pre-fetch 匹配您的地理空间约束的文档列表,并将其作为约束输入您的 SPARQL(这应该是高性能的)

大致如下:

let $uris := cts:uris((), (), cts:path-geospatial-query("/people_data/location",  cts:circle(10, cts:point(59,28))))
return sem:sparql('
  SELECT *
  WHERE{
    ?person </posted> ?question .
    FILTER (?person = ?people) .
  }
', map:entry("people", $uris))

对上面的例子稍微更方便、更好优化的方法是使用 Optic API 重写它。它专为提供一种高性能的方式来弥合各种数据模型之间的差距而设计。

根据上面的代码推断,我认为它会在光学代码中读取这样的内容:

import module namespace op="http://marklogic.com/optic" at "/MarkLogic/optic.xqy";

let $people := op:from-lexicons(
  map:entry("people", cts:uri-reference()),
  "lexicon"
)
  => op:where(
    cts:path-geospatial-query("/people_data/location", cts:circle(10, cts:point(59,28)))
  )

let $questions := op:from-sparql('SELECT * WHERE { ?person </posted> ?question. }', "sparql")

return $people
  => op:join-inner(
    $questions,
    op:on(
      op:view-col("lexicon", "people"),
      op:view-col("sparql", "person")
    )
  )
  =>op:result()

如果没有合适的数据和索引,测试起来有点困难,但我希望这足以让你入门。

您可以在此处找到有关它的介绍性文档:

https://docs.marklogic.com/guide/app-dev/OpticAPI

API 参考可以在这里找到:

https://docs.marklogic.com/op

HTH!