SPARQL Geospatial Queries (MarkLogic) - PullRequest
0 голосов
/ 28 мая 2019

Продолжение предыдущего вопроса здесь . Там, где было отмечено, что избегать fn:doc() следует избегать в запросах SPARQL. Однако для геопространственных запросов, кроме кода, показанного ниже, я не могу найти альтернативное решение. Я также использовал этот запрос, и время его выполнения очень медленное. Для большего набора данных он достигнет 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())

======= Обновление ========

Вопрос перенесен на тему

1 Ответ

1 голос
/ 29 мая 2019

Здесь я вижу два варианта:

  • либо вы используете геопространственную функцию, встроенную в MarkLogic, чтобы находить геопространственное перекрытие непосредственно внутри SPARQL, предпочтительно сравнивая свойство RDF, а не значение из индекса пути (все еще неоптимального)
  • лучше: предварительно извлечь список документов, соответствующих вашему геопространственному ограничению, и передать это как ограничение в ваш 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

НТН!

...